how do I concatenate 3 lists using a list comprehension? - python

In python, how do I concatenate 3 lists using a list comprehension?
Have:
list1 = [1,2,3,4]
list2 = [5,6,7,8]
list3 = [9,10,11,12]
Want:
allList = [1,2,3,4,5,6,7,8,9,10,11,12]
I tried using a list comprehension, but I'm not very good at them yet. These are what I have tried:
allList = [n for n in list1 for n in list2 for n in list3 ]
this was a bad idea, obviously and yielded len(list1)*len(list2)*len(list3) worth of values. Oops. So I tried this:
allList = [n for n in list1, list2, list3]
but that gave me allList = [list1, list 2, list3] (3 lists of lists)
I know you can concatenate using the + operator (as in x = list1 + list2 + list3)but how do you do this using a simple list comprehension?
There is a similar question here: Concatenate 3 lists of words , but that's for C#.

A better solution is to use itertools.chain instead of addition. That way, instead of creating the intermediate list list1 + list2, and then another intermediate list list1 + list2 + list3, you just create the final list with no intermediates:
allList = [x for x in itertools.chain(list1, list2, list3)]
However, an empty list comprehension like this is pretty silly; just use the list function to turn any arbitrary iterable into a list:
allList = list(itertools.chain(list1, list2, list3))
Or, even better… if the only reason you need this is to loop over it, just leave it as an iterator:
for thing in itertools.chain(list1, list2, list3):
do_stuff(thing)
While we're at it, the "similar question" you linked to is actually a very different, and more complicated, question. But, because itertools is so cool, it's still a one-liner in Python:
itertools.product(list1, list2, list3)
Or, if you want to print it out in the format specified by that question:
print('\n'.join(map(' '.join, itertools.product(list1, list2, list3))))

Here are some options:
>>> sum([list1, list2, list3], [])
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> list1 + list2 + list3
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
With comprehension: (it's really not necessary)
>>> [x for x in sum([list1, list2, list3], [])]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

You can do allList = list1 + list2 + list3 instead of allList = [x for x in list1 + list2 + list3]

If you put the lists that you want to concatenate in a list literal, you can write a nested for loop in the list comprehension to loop over all elements.
allList = [n for l in [list1, list2, list3] for n in l]
This solution does not need any extra imports or other functions to concatenate the lists.

As an alternative to all of the other options, you could also just splat them all into a new list for comprehension (if you don't explicitly require a comprehension to generate the concatenated list):
>>> list1 = [1, 2, 3, 4]
>>> list2 = [5, 6, 7, 8]
>>> list3 = [9, 10, 11, 12]
>>> allList = [*list1, *list2, *list3]
>>> allList
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
I couldn't come up with any reason why the new list would need deriving from a comprehension explicitly since you could just nest this inside a comprehension if desired, e.g. if you had other logic to run on the merged list:
>>> [val + 3 for val in [*list1, *list2, *list3]]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
If performance is a big deal, you can also just make the splatted list a generator function instead:
>>> [val + 3 for val in (*list1, *list2, *list3)]
[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

Simply do list1 + list2 + list3
>>> list1 = [1,2,3,4]
>>> list2 = [5,6,7,8]
>>> list3 = [9,10,11,12]
>>>
>>> list1 + list2 + list3
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
If you want to remove duplicates, run below code:
>>> list(set(list1 + list2 + list3))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Related

Try To Print Map as str/list/join without succeess

def intersection(list_1, list_2):
return map(lambda list0 : list(dict.fromkeys(list0)), [x for x in list_1 if x in list_2 ])
print(intersection([5, 5, 6, 6, 7, 7], [1, 5, 9, 5, 6]))
In lambda the func that deletes duplicate and in [ ] the list (from list comprehension) the transfered to the func by map.
When I try to turn it into a list / str / join this error accourced.
What can I do and why is this happening ?
I added one example run that suppose to print [5,6] but returns error.
Be noticed that the list itself ([ ]) reutrns alone: [5, 5, 6, 6] because of the duplicates in the original lists.
Also if I change the code from one line to block og code it works:
def intersection(list_1, list_2):
my_list = [x for x in list_1 if x in list_2]
small_func = lambda list0 : list(set(list0))
return small_func(my_list)
returns: [5,6]
Thanks !
I don't think you need map here. Your idea was right to convert to dictionary and than convert back to list but you have to do that only once.
def intersection(list_1, list_2):
return list(dict.fromkeys([x for x in list_1 if x in list_2]))
print (intersection([5, 5, 6, 6, 7, 7], [1, 5, 9, 5, 6]))

Recursive method to zip list?

I have got a nested list of list that looks like the following,
list1 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
However, I would like to find out a method to concatenate the first index of each list with the first index of the other list.
list1 = [[1,4,7,10],[2,5,8,11],[3,6,9,12]]
I have tried doing list comprehension by using the following code
list1 = [[list1[j][i] for j in range(len(list1)) ] for i in range(len(list1[0])) ]
# gives me
# list1 = [[1,4,7,10],[2,5,8,11],[3,6,9,12]]
However, i was hoping alternative methods to achieve the same results, hopefully something that is simpler and more elegant.
Thanks in advance.
zip is a built-in method and does not require outside packages:
>>> list1 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
>>> print([list(x) for x in zip(*list1)])
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Notice the *list1! This is needed since list1 is a nested list, so the * unpacks that list's elements to the zip method to zip together. Then, since zip returns a list of tuples we simply convert them to lists (as per your request)
A possible recursion solution can utilize a generator:
def r_zip(d):
yield [i[0] for i in d]
if d[0][1:]:
yield from r_zip([i[1:] for i in d])
print(list(r_zip(list1)))
Output:
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
x = min([len(list1[i]) for i in range(len(list1))])
[[i[j] for i in list1] for j in range(x)]
Or try using:
>>> list1 = [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]
>>> list(map(list, zip(*list1)))
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
>>>

Combine two lists while maintaining order and removing duplicates [duplicate]

This question already has answers here:
Python: Combining two lists and removing duplicates in a functional programming way
(6 answers)
Closed 4 years ago.
I'd like to combine two lists while maintaining order and not allowing duplicates.
list1 = [4, 5, 2, 6]
list2 = [4, 1, 2, 9, 6]
output -> [4, 5, 2, 6, 1, 9]
What I've tried is list(set(list1) | set(list2)) but this does not maintain order. Is there a way to do this with list comprehension?
You can use the dict.fromkeys method:
list(dict.fromkeys(list1 + list2))
If you're using Python 3.6 or earlier versions, you can use collections.OrderedDict in place of dict.
list1 = [4, 5, 2, 6]
list2 = [4, 1, 2, 9, 6]
list3 = [item for item in list2 if item not in list1]
list1 += list3
much more readable than using sets
You could do the following for an O(n) solution:
list1 = [4, 5, 2, 6]
list2 = [4, 1, 2, 9, 6]
s1 = set(list1)
result = list1 + [e for e in list2 if e not in s1]
print(result)
Output
[4, 5, 2, 6, 1, 9]

Ordered list from elements of a 2 dimensional list?

I have a 2 dimensional list. Example:
list = [[1,4,7], [2,5,8], [3,6,9]]
I need to make a new list whose elements are the elements of each sub-element preserving the order.
Example:
final_list = [1,2,3,4,5,6,7,8,9]
Q: The new list must take the first element of each list first, then the
second, and so on..
A:
You can use zip and a list comprehension.
list_1 = [1,4,7]
list_2 = [2,5,8]
list_3 = [3,6,9]
print([x for lst in zip(list_1, list_2, list_3) for x in lst])
# outputs > [1, 2, 3, 4, 5, 6, 7, 8, 9]
For your new list, you could do the same, but first unpack the list with a *
new_list = [[1,4,7], [2,5,8], [3,6,9]]
print([x for lst in zip(*new_list) for x in lst])
# outputs > [1, 2, 3, 4, 5, 6, 7, 8, 9]
first transpose the list matrix with zip then chaining all the inner list together with itertools
also rename variable list to lst, not a good practice to use builtin list as variable name
import itertools
lst = [[1,4,7], [2,5,8], [3,6,9]]
final_list = list(itertools.chain.from_iterable(zip(*lst)))
# final_list = [1, 2, 3, 4, 5, 6, 7, 8, 9]

Comparing Two Lists to Find Bigger List

I have two lists and need to compare them by their largest element, if that is tied, their 2nd largest element, and if that is tied, 3rd largest etc iterating to the entire array.
For example:
list1= [0,2,3,6,12]
list2= [1,2,3,6,12]
list3= [1,4,5,8,12]
list4= [1,4,5,9,12]
So list4 > list3 > list2 > list1.
I wrote a function that accomplishes this:
def compare(x,y):
if sorted(x)==sorted(y):
return "Tie"
for index in range(len(x)-1,-1,-1):
if sorted(x)[index]>sorted(y)[index]:
return x
elif sorted(x)[index]<sorted(y)[index]:
return y
I was wondering if there was a much neater and more efficient way of writing the function because it doesn't seem very Pythonic.
Edit: comparing lists by using "<" and ">" will sort the lists from the smallest index to largest index, not largest index to smallest index. Reversed would make ">" and "<" the simplest solutions.
How about this?
>>> list1= [0,2,3,6,12]
>>> list2= [1,2,3,6,12]
>>> list3= [1,4,5,8,12]
>>> list4= [1,4,5,9,12]
>>> def sort_lists_by_maxes(*lists):
return sorted(lists, key=lambda x: sorted(x, reverse=True), reverse=True)
>>> sort_lists_by_maxes(list1, list2, list3, list4)
[[1, 4, 5, 9, 12], [1, 4, 5, 8, 12], [1, 2, 3, 6, 12], [0, 2, 3, 6, 12]]
The lists are compared by their individually sorted values, and you can feed as many lists as you would like into the function as arguments.
sorted of sorted is good, but I'm partial to:
#!/usr/local/cpython-3.3/bin/python
list1 = [0, 2, 3, 6, 12]
list2 = [1, 2, 3, 6, 12]
list3 = [1, 4, 5, 8, 12]
list4 = [1, 4, 5, 9, 12]
metalist = [ list1, list2, list3, list4 ]
for sublist in metalist:
sublist.sort(reverse=True)
metalist.sort(reverse=True)
print(metalist)
It should be faster and take less memory. It's also more clear to novices.

Categories