How to zip lists in a list [duplicate] - python

This question already has answers here:
Expanding tuples into arguments
(5 answers)
Closed 6 months ago.
I want to zip the following list of lists:
>>> zip([[1,2], [3,4], [5,6]])
[[1,3,5], [2,4,6]]
This could be achieved with the current zip implementation only if the list is split into individual components:
>>> zip([1,2], [3,4], [5,6])
(1, 3, 5), (2, 4, 6)]
Can't figure out how to split the list and pass the individual elements to zip. A functional solution is preferred.

Try this:
>>> zip(*[[1,2], [3,4], [5,6]])
[(1, 3, 5), (2, 4, 6)]
See Unpacking Argument Lists:
The reverse situation occurs when the arguments are already in a list or tuple but need to be unpacked for a function call requiring separate positional arguments. For instance, the built-in range() function expects separate start and stop arguments. If they are not available separately, write the function call with the *-operator to unpack the arguments out of a list or tuple:
>>> range(3, 6) # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args) # call with arguments unpacked from a list
[3, 4, 5]

Related

python reorder nested list from row to column [duplicate]

This question already has answers here:
Zip lists in Python
(10 answers)
Closed 2 years ago.
My input is
tbl_ports = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
And my expected output is
[[1,5,9], [2,6,10], [3,7,11], [4,8,12]]
My limit was to do the following to create the output reorder_list
reorder_list = []
for i in range(len(tbl_ports)):
for col in tbl_ports:
reorder_list.append(col[i])
reorder_list=[1, 5, 9, 2, 6, 10, 3, 7, 11]
How can I contain them in a list of 3 elements?
To fix the code that you already have, you need to create a new list every time a row is complete, such as:
reorder_list = []
for i in range(len(tbl_ports)):
reorder_list.append([])
for col in tbl_ports:
reorder_list[-1].append(col[i])
Which would yield the following result:
[[1, 5, 9], [2, 6, 10], [3, 7, 11]]
You can also use a more pythonic method of solving the problem,
list(zip(*tbl_port))
Which would yield a list of tuples:
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
If you want a list of lists, then you can simply just use list comprehension:
[list(e) for e in zip(*tbl_port)]
Edit:
for an explanation of why zip(*list) works, you need to know what zip does.
zip is a function in python that takes in multiple lists, and outputs a generator of lists for each element in every corresponding list. So zip([1, 2, 3], [4, 5, 6]) would yield [(1, 4), (2, 5), (3, 6)].
the * basically expands the input into multiple positional arguments, where function(*[1, 2, 3, 4]) is equivalent to function(1, 2, 3, 4)
So the code passed in the input array as a list of arguments to the zip function, which then outputs the result in the order that you want.
The only remaining problem is that zip generates a generator instead of an actual list.
To solve that problem, simply call the list function on a generator to convert it into a list, or pass it in a list comprehension to yield the desired result.
This is exactly what the zip() function is for.
list(zip([1,2,3,4],'abcd'))
You can use the unpack syntax " * " to make python unpack your lists to the zip function.
tbl_ports = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
reorder_list = list(zip(*tbl_ports))

Concatenate multiple ranges in a list [duplicate]

This question already has answers here:
Concatenating two range function results
(8 answers)
How can I generate a list of consecutive numbers? [duplicate]
(8 answers)
Closed 3 years ago.
in python is there a way to create of list that will skip numbers and will continue after skipping? something like the following code:
x = [1...3, 6...10]
print(x)
# [1,2,3,6,7,8,9,10]
Well its easy to write a for loop and then skip each defined index/value, or i can just use range, what I am looking for is a shorter more readable line. If not I can understand.
Simplest way to do this is to call range() and unpack result inside list assignment.
x = [*range(1, 4), *range(6, 11)]
Alternatively you can use itertools.chain:
>>> import itertools
>>> list(itertools.chain(range(1, 5), range(20, 25)))
[1, 2, 3, 4, 20, 21, 22, 23, 24]
If numpy is an option, you can use np.r_ to concatenate slice objects:
import numpy as np
np.r_[1:4, 6:11]
# array([ 1, 2, 3, 6, 7, 8, 9, 10])
You can turn it into a recursive function:
def recursive_ranges(ranges):
if len(ranges) == 1:
return list(range(*ranges[0]))
else:
return list(range(*ranges[0])) + recursive_ranges(ranges[1:])
You can then call this, specifying ranges as a list of lists:
ranges = [[1, 4], [6, 11]]
recursive_ranges(ranges)
# [1, 2, 3, 6, 7, 8, 9, 10]
Note the *ranges[0] is used to unpack the elements in ranges[0] into individual arguments. Essentially the recursive function keeps grabbing the first element of ranges, each element of which is a two-element array, and passing those numbers into the range() method as two different values instead of one array. That's what the * does, it unpacks the array. First call, you unpack [1, 4] into range(1, 4) and then append the next call of the recursive function to it.
Basically this unpacks into the following:
list(range(1, 4)) + list(range(6, 11))
but you get to use a much more compact syntax, just passing a list of lists.

Extracting corresponding elements of sublist [duplicate]

This question already has answers here:
Transpose nested list in python
(4 answers)
Transpose list of lists
(14 answers)
Closed 5 years ago.
It should work like
input: list([[1,1,1],[2,2,2],[3,3,3]])
output: [[1,2,3], [1,2,3], [1,2,3]]
so far i have done this:
def list(m):
list2=[]
for i in range(0, len(m)):
list2.append([x[i] for x in m])
return(list2)
It's not working every time..
For example:
it's working for
input: list([[1,1,1],[2,2,2],[3,3,3]])
but not for
input: list([[1,3,5],[2,4,6]])
You would usually do that in Python using the zip function:
inp = list([[1,1,1],[2,2,2],[3,3,3]])
output = list(map(list, zip(*inp)))
print(output)
>>> [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
The additional map call is to convert the elements returned by zip, that are tuples, into lists, but if you are okay with tuples you can just do:
inp = list([[1,1,1],[2,2,2],[3,3,3]])
output = list(zip(*inp))
print(output)
>>> [(1, 2, 3), (1, 2, 3), (1, 2, 3)]
Also, the outer list is only necessary in Python 3, where zip returns a generator, but not in Python 2.

Can a set have lists as its elements? [duplicate]

This question already has answers here:
Add list to set
(13 answers)
How to make a set of lists
(4 answers)
How to convert list of lists to a set in python so I can compare to other sets?
(3 answers)
Closed 5 years ago.
I am trying to get unique lists which can consist duplicate values,can I use sets to get unique lists?
To be more specific ,here is an example:
my_list=[[1,2,1],[1,2,2],[1,2,2],[1,1,2],[2,2,2]]
what i would want is :
set_list=[[1,2,1],[1,2,2],[1,1,2],[2,2,2]]
is this possible?
Thanks in advance for your kind response :)
No, a list is not hashable. You will get the following error:
TypeError: unhashable type: 'list'
Given the list only contains hashable objects, you can however convert the list to a tuple and add the tuples. So you could do something like:
>>> my_list=[[1,2,1],[1,2,2],[1,2,2],[1,1,2],[2,2,2]]
>>> set_tuples = {tuple(a_list) for a_list in my_list}
>>> set_tuples
{(1, 2, 2), (1, 2, 1), (2, 2, 2), (1, 1, 2)}
You can then for instance construct a uniqueness filter with:
my_list=[[1,2,1],[1,2,2],[1,2,2],[1,1,2],[2,2,2]]
result = []
unique_set = set()
for sublist in my_list:
the_tuple = tuple(sublist)
if the_tuple not in unique_set:
unique_set.add(the_tuple)
result.append(sublist)
So all operations on the set are done with tuples. This gives:
>>> result
[[1, 2, 1], [1, 2, 2], [1, 1, 2], [2, 2, 2]]
Lists are not hashable, but you can have a set of tuples, :
set(map(tuple, my_list))
# {(1, 1, 2), (1, 2, 1), (1, 2, 2), (2, 2, 2)}

Why arguments to dictionary[] are interpreted as a single key? [duplicate]

This question already has answers here:
When are parentheses required around a tuple?
(3 answers)
Closed 6 years ago.
If I declare a dictionary like:
a = {(1, 2, 3): 10, (4, 5, 6):20}
the I can reference the elements as using the keys as:
a[(1, 2, 3)]
why this:
a[1, 2, 3]
results in the same operation? If is were a function it should raise an error since I am passing three parameters instead of one.
a[1, 2, 3]
It takes as a tuple.
>>>a = 1,2,3
>>>type(a)
tuple
1, 2, 3 is a tuple, just like (1, 2, 3). Tuples are defined by the commas. The parentheses are for grouping in cases that might otherwise be ambiguous.
You're still passing in a tuple, just using other syntax.
(a, b, c, d) is the same as a, b, c, d, they both construct a tuple.
Because declaring x,y,z is a implicit way of declaring a tuple. Try this:
>>> n = 1,2
>>> n
(1, 2)

Categories