-1

I have a list of list like below:

[[1,345,0,304],[0,345,678,946,90],[0,23,3,56,3,5,9,0]]

Now I want to append a new number (same number) to each of internal list at the end.

so result should be like:

[[1,345,0,304,90],[0,345,678,946,90,90],[0,23,3,56,3,5,9,0,90]]

I want to use a list comprehension as I don't want to do it the normal way by iterating over each internal list in main list and then use a temporary list to add to it.

Any help?

Baktaawar
  • 7,086
  • 24
  • 81
  • 149
  • 1
    You can go a long way in improving this question by clarifying your intent. You claim that you want to append to each list using a list comprehension, but you've selected an answer which creates a copy, appending to those lists instead of the lists you mention. If that's what you want, please edit your question to make that clear. – Arya McCarthy Sep 16 '17 at 03:33

5 Answers5

3

you can just use list addition to accomplish this:

[l + [90] for l in lists]
acushner
  • 9,595
  • 1
  • 34
  • 34
  • This is tremendously wasteful because it creates copies of the list. It doesn't, in fact, append each list. It creates brand new lists. Imagine the asymptotic case of a 1000x1000 list of lists. – Arya McCarthy Sep 16 '17 at 03:29
  • @AryaMcCarthy yes it's wasteful, but if you read OP's question it's what he/she wanted. – acushner Sep 19 '17 at 14:04
1

Approaches

Native Python (@acushner presented this first):

lsts = [[1,345,0,304], [0,345,678,946,90], [0,23,3,56,3,5,9,0]]
[lst + [90] for lst in lsts]

Alternatively, with itertools.chain:

import itertools as it

[list(it.chain(lst, [90])) for lst in lsts]

For fun, a third-party library more-itertools (pip install more_itertools):

import more_itertools as mit

[list(mit.padded(lst, fillvalue=90, n=len(lst)+1)) for lst in lsts]

Caveat

Some answers attempt to mutate a list while iterating. While those options give equivalent results, are possibly more memory efficient and may even be faster for larger data for this specific problem, they are arguably non-pythonic and not recommended practices.

From the Python docs:

It is sometimes tempting to change a list while you are looping over it; however, it is often simpler and safer to create a new list instead.

This is especially true when removing or inserting elements from a list while iterating it. The latter approaches adopt this convention of creating a new list. However, for certain innocuous circumstances, a compromise may be iterating over a copy of the nested list:

lists = [[1,345,0,304], [0,345,678,946,90], [0,23,3,56,3,5,9,0]]
for lst in lists[:]:
    lst.append(90)
lists

Otherwise, default to @acushner's approach, which is the next performant option discussed here.

pylang
  • 40,867
  • 14
  • 129
  • 121
  • This is tremendously wasteful because it creates copies of the list. It doesn't, in fact, append each list. It creates brand new lists. Imagine the asymptotic case of a 1000x1000 list of lists. – Arya McCarthy Sep 16 '17 at 03:29
  • No copies are made. New lists are created. This is intentional and a common convention with list comprehensions in Python. What alternative do you suggest? – pylang Sep 16 '17 at 03:40
0

This also works

lists = [[1,345,0,304],[0,345,678,946,90],[0,23,3,56,3,5,9,0]]
[l.append(90) for l in lists]
print(lists)

[[1, 345, 0, 304, 90], [0, 345, 678, 946, 90, 90], [0, 23, 3, 56, 3, 5, 9, 0, 90]]

Serjik
  • 10,543
  • 8
  • 61
  • 70
  • 2
    This solution is best because it mutates the data structure rather than creating a new one. That being said, this is not how you should use list comprehensions. The question is best answered with a for-loop. – Arya McCarthy Sep 16 '17 at 02:30
  • Could you explain why list comprehensions shouldn't be used for this? – Simon Sep 16 '17 at 02:34
  • @Serjik This is not correct. It won't work since append returns None – Baktaawar Sep 16 '17 at 02:45
  • @Baktaawar It absolutely works, just print the result, None is because append does not return a value – Serjik Sep 16 '17 at 02:58
  • @Arya McCarthy : as your comment the best, why any other answers get an upvote and me getting the down ??? – Serjik Sep 16 '17 at 03:01
  • No clue. Your answer is best. My best guess is that someone is trying to popularize their own answer. – Arya McCarthy Sep 16 '17 at 03:30
0

Another option

lists = [[1,345,0,304], [0,345,678,946,90], [0,23,3,56,3,5,9,0]]

for lst in lists:
    lst.append(90)

print lists
[[1, 345, 0, 304, 90],[0, 345, 678, 946, 90, 90],[0, 23, 3, 56, 3, 5, 9, 0, 90]]
mwweb
  • 7,625
  • 4
  • 19
  • 24
  • Consider mutating a copy of the nested list (see post for rationale). Also for clarity, I would swap the names of `lst` and `lists`. Otherwise, this is a good answer. – pylang Sep 16 '17 at 07:19
  • Mutating the same list you are iterating is not a best-practice. In this case, it is harmless since you are not removing items, but a safer habit is to iterate a copy, e.g. `lists[:]`. There are several posts of this kind https://stackoverflow.com/questions/1637807/modifying-list-while-iterating. Just substitute `for lst in lists[:]:`. – pylang Sep 16 '17 at 15:33
  • @pylang he is not asking to iterate a copy – mwweb Sep 16 '17 at 15:54
  • I was suggesting an idiom to improve your answer. See the cavaet I posted for more information. Thanks for your post. – pylang Sep 16 '17 at 16:04
0

And another one:

lists = [[1,345,0,304],[0,345,678,946,90],[0,23,3,56,3,5,9,0]]
for _ in map(lambda x: x.append(90), lists):
    pass
Yaroslav Surzhikov
  • 1,568
  • 1
  • 11
  • 16