1

The parameter represents a message file that is already open for reading, and which contains one message per line.

Read and return the contents of the file as a list of messages, in the order in which they appear in the file. Strip the newline from each line.

def read_messages(file):
    """
    """
    message = []
    for line in file:
        new_line = line.strip()
        message.append(new_line)
    return message

well, I know this is not the correct answer but I have no idea how can I fix it.

Kara
  • 6,115
  • 16
  • 50
  • 57
Polsop
  • 175
  • 3
  • 11
  • 3
    `lines = [line.rstrip('\r\n') for line in file]` - that's all you need and most likely not worth beign put in a separate function. – ThiefMaster Nov 05 '15 at 23:17
  • Unless you have a trick question where the file has a line with a carriage return before a carriage return and newline combination, and @ThiefMaster's comment will wrongly delete that character. Python's [default universal newline handling](http://stackoverflow.com/questions/4599936/handling-r-n-vs-n-newlines-in-python-on-mac-vs-windows) is to present newlines as `\n` regardless of OS, so I suggest you should only `.rstrip('\n')` to get rid of newlines. – TessellatingHeckler Nov 05 '15 at 23:46

1 Answers1

2

Let's see your function step by step:

def read_messages(file):

Function read_messages takes a single parameter, file; begin function.

    message = []

Let variable message be the empty list ([]).

    for line in file:

For each line in file, let variable line be such a line.

        new_line = line.strip()

Let variable new_line be the line variable, with all whitespaces at the beginning and end of it stripped.

        message.append(new_line)

Append new_line to message.

    return message

Return variable message; end function.

The algorithm is correct (why did you said otherwise?), but can be simplified, first of all, the pattern...

x = []
for ...:
    something = ...
    x.append(something)
doSomething(x) # Can be `return` too

Can be simplied to a list comprehension. List comprehensions are a means for constructing a list in a simple and easy to read expression, without doing all the hassle to create the list, adding to it, and returning it. According to the previous pattern, you can do something like...

doSomething([ something for ... ])

That's the same as the pattern above! Now, applied to your code:

return [ ??? for line in file ]

What should we put instead of ??? there? Well, you must put the code that calculates new_line (line.strip()) of course! That's because new_line can be tought of as a synonym for line.strip(), as line.strip() has no side effects (doing line.strip() will always give the same result regardless of the time at which it's called, given that line is the same). So...

return [ line.strip() for line in file ]

You can use that, or if you don't want to lose the whitespace at the beginning, then...

return [ line.rstrip() for line in file ]

rstrip() does the same as strip(), except that it does not removes whitespace at the beginning of the string.

So, your function becomes...

def read_messages(file):
    return [ line.rstrip() for line in file ]

That's all according to your requirements, but let's do a few more optimizations!

If any line is empty, or contains just whitespace, would you want that line to go into the list? I won't, at least. So how would you fix that? I would take the list comprehension, and filter out all the empty lines, or those made up of just whitespace. So, the thing becomes...

import string

def read_messages(file):
    return filter(lambda x: not all(map(lambda y: y in string.whitespace, x)), [ line.rstrip() for line in file ])

Now, what's that? First of all, a lambda is like a function that you can declare as an expression anywhere. The format is lambda parameters...: return_value. Did you noticed that return_value stuff? Well, it happens that lambdas can only contain a single expression, and they implicitly return that expression. So, for example, lambda x: x + 1 is a function that takes a single parameter x and returns x + 1.

Now, we have three new functions: map, filter, and all:

  • map(f, list): Takes a function f and calls f(x) for each x in list, creating another list holding the result of that. It's equivalent to [ f(x) for x in list ].
  • filter(f, list): Takes a function f and creates a new list out of list. For any x in list, if f(x) is True, then x goes into the new list. Otherwise, it is discarded. It's equivalent to [ x for x in list if f(x) ].
  • all(list): Takes a list and returns True if all elements in the list are True, False otherwise.

Finally, string.whitespace is a list of all whitespace characters.

So, this new construct can be said in Plain English? Of course!

Return a new list made up of each line in the file, with its trailing whitespace removed, if the line is not empty and not all characters in that line are whitespace characters.

Undo
  • 25,519
  • 37
  • 106
  • 129
3442
  • 8,248
  • 2
  • 19
  • 41