Using zip () to rotate a list

I have a set of records returned from a database in the following form:

data = [ ["date", "value1a", "value2a", "value3a", ...], ["date", "value1b", "value2b", "value3b", ...] ] 

I want to turn this set of strings into a list like

 [ [("date", "value1a"), ("date", "value1b"), ... ], [("date", "value2a"), ("date", "value2b"), ... ] ] 

I know that zip() does such things, but I don’t understand how to get the date in each record (and make them tuples). The length of the rows returned from the database will not always be the same, but I will know the expected length in each call.

+4
source share
4 answers
 data = [["date_a", "1a", "2a", "3a"], ["date_b", "1b", "2b", "3b"]] print zip(*(zip(itertools.repeat(ls[0]), ls[1:]) for ls in data)) 

gives

 [(('date_a', '1a'), ('date_b', '1b')), (('date_a', '2a'), ('date_b', '2b')), (('date_a', '3a'), ('date_b', '3b'))] 

See comments for some useful options.

+4
source

Use itertools repeat for the first element:

 zip(itertools.repeat(ls[0]), ls[1:]) 
+2
source

Edit: this was based on the original question under the assumption that the data would be in one list, and not in multiple input lists. Editing the question made it clear that this is not so, so I would advise you to follow the decision of Janne Karila .

Assuming you know how many different values ​​there are, this is a good solution using the itertools ' grouper() recipe :

 import itertools def grouper(n, iterable, fillvalue=None): args = [iter(iterable)] * n return itertools.zip_longest(fillvalue=fillvalue, *args) data = ["date", "1a", "2a", "3a", "1b", "2b", "3b", "1c", "2c", "3c"] first = data.pop(0) print([list(zip(itertools.repeat(first), items)) for items in zip(*grouper(3, data))]) 

Gives us:

 [ [('date', '1a'), ('date', '1b'), ('date', '1c')], [('date', '2a'), ('date', '2b'), ('date', '2c')], [('date', '3a'), ('date', '3b'), ('date', '3c')] ] 

Note that this will populate lists with None if the values ​​are not enough.

Naturally, you can use the understanding of the generator instead of understanding the list , if you just want to iterate over it, for example, not displaying it, For example:

 (zip(itertools.repeat(first), items) for items in zip(*grouper(3, data))) 

Note that I'm using Python 3.x, so under 2.x, wherever I use zip() , you probably want itertools.izip() , and itertools.zip_longest() will become itertools.izip_longest() .

Note that the best way to do this is by assuming that you know what determines the value that should be in the first list, what should be in the second list, etc.

 import itertools import operator data = ["date", "1a", "2a", "3a", "1b", "2b", "3b", "1c", "2c", "3c"] first = data.pop(0) print([list(zip(itertools.repeat(first), items)) for _, items in itertools.groupby(sorted(data), operator.itemgetter(0))]) 

What produces:

 [ [('date', '1a'), ('date', '1b'), ('date', '1c')], [('date', '2a'), ('date', '2b'), ('date', '2c')], [('date', '3a'), ('date', '3b'), ('date', '3c')] ] 

Naturally, this only works for this example, assuming that your real data is different, you need to change operator.itemgetter(0) to a function that determines which list your item should be grouped into.

Please note that we can encapsulate our preliminary work:

 def prefix(iterable, prefix): """Returns every element of an iterable prefixed with a given value.""" #prefix("ABCDEFG", "x") --> ("x", "A"), ("x", "B"), ("x", "C"), ("x", "D"), ... return zip(itertools.repeat(prefix), iterable) 

And then we just:

 (prefix(items, first) for items in zip(*grouper(3, data))) 

and

 (prefix(items, first) for _, items in itertools.groupby(sorted(data), operator.itemgetter(0))) 

This is more readable.

+2
source

This can also be achieved using a simple list comprehension technique.

 data = [ ["date1", "value1a1", "value2a1", "value3a1"], ["date2", "value1b2", "value2b2", "value3b2"] ] result = map(list, zip(*[[(x[0], x[i]) for x in data] for i in range(1,len(x))])) [ [('date1', 'value1a1'), ('date1', 'value2a1'), ('date1', 'value3a1')], [('date2', 'value1b2'), ('date2', 'value2b2'), ('date2', 'value3b2')] ] 
0
source

Source: https://habr.com/ru/post/1413551/


All Articles