2
\$\begingroup\$

As of reading the following input.txt file:

1 6 14
1 2 7
1 3 9
2 3 10
2 4 15
3 6 2
3 4 11
4 5 6
5 6 9

I wanted to make a list of lists containing each line as a list of integers

[[1, 6, 14],
 [1, 2, 7],
 [1, 3, 9],
 ...
 [5, 6, 9]] 

I achieved that by doing the following

with open('input.txt', 'r') as f:
    # gets lines as list of strings [['1, 2, 3,', ...]]     
    nodes_list = [n.split() for n in f.readlines()] 
    # convert strings inside the lists to int's [[1, 2, 3], ...]
    nodes_list = [[int(y[0]), int(y[1]), int(y[2])] for y in nodes_list]

Is there any way that I can achieve the same with a single comprehension list, without the need of having two separated ones? If not, maybe some cleaner way of doing it?

\$\endgroup\$

3 Answers 3

4
\$\begingroup\$

What about:

with open('input.txt', 'r') as f:  
    nodes_list = [[int(item) for item in line.split()] for line in f]

Notice how:

  1. rather than iterating over f.readlines(), which creates a list of the lines in the file, we iterate over f, which produces the same result, but as a generator,
  2. rather than first creating a potentially huge list of lists of strings, then converting it to a list of lists of ints, only a single row is instantiated at a time.
\$\endgroup\$
2
  • \$\begingroup\$ I would also add, that [int(item) for ...] is easier to read than list(map(int, ...)) \$\endgroup\$
    – oliverpool
    Jan 27, 2016 at 13:45
  • 1
    \$\begingroup\$ Have to apologize to @mleyfman, but your answer is more clear and concise. Thanks. \$\endgroup\$
    – streppel
    Jan 27, 2016 at 16:42
4
\$\begingroup\$

You can use a map to give you what you want in a single line:

with open('input.txt', 'r') as f:
    nodes = [list(map(int, line.split())) for line in f]

An explanation of how it works:

f.readlines() iterates over the lines, with line endings removed

line.split() gives you an iterable over the space-separated characters

map(int, ...) does the conversion to int for every element

list(...) converts it to a list to give you a list of lists

\$\endgroup\$
2
  • \$\begingroup\$ I have never managed to look at map and filter the same after reading Guido's plans to cut them from Py3K. \$\endgroup\$
    – Jaime
    Jan 27, 2016 at 6:57
  • 2
    \$\begingroup\$ for line in f.readlines() can be rewritten as for line in f (uses a generator) \$\endgroup\$
    – oliverpool
    Jan 27, 2016 at 13:39
0
\$\begingroup\$

Just a very small note, that you don't need explicitly use 'r' when opening a file in read mode. That's the default mode, so there's no difference between open('input.txt', 'r') and open('input.txt'). You may as well use the latter for brevity and readability.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.