opposite of zip()?
Matt Nordhoff
mnordhoff at mattnordhoff.com
Mon Dec 17 11:47:24 EST 2007
Rich Harkins wrote:
> igor.tatarinov at gmail.com wrote:
>> Given a bunch of arrays, if I want to create tuples, there is
>> zip(arrays). What if I want to do the opposite: break a tuple up and
>> append the values to given arrays:
>> map(append, arrays, tupl)
>> except there is no unbound append() (List.append() does not exist,
>> right?).
>>
>
> list.append does exist (try the lower-case flavor).
>
>> Without append(), I am forced to write a (slow) explicit loop:
>> for (a, v) in zip(arrays, tupl):
>> a.append(v)
>>
>
> Except that isn't technically the opposite of zip. The opposite would
> be a tuple of single-dimensional tuples:
>
> def unzip(zipped):
> """
> Given a sequence of size-sized sequences, produce a tuple of tuples
> that represent each index within the zipped object.
>
> Example:
> >>> zipped = zip((1, 2, 3), (4, 5, 6))
> >>> zipped
> [(1, 4), (2, 5), (3, 6)]
> >>> unzip(zipped)
> ((1, 2, 3), (4, 5, 6))
> """
> if len(zipped) < 1:
> raise ValueError, 'At least one item is required for unzip.'
> indices = range(len(zipped[0]))
> return tuple(tuple(pair[index] for pair in zipped)
> for index in indices)
>
> This is probably not the most efficient hunk of code for this but this
> would seem to be the correct behavior for the opposite of zip and it
> should scale well.
>
> Modifying the above with list.extend would produce a variant closer to
> what I think you're asking for:
>
> def unzip_extend(dests, zipped):
> """
> Appends the unzip versions of zipped into dests. This avoids an
> unnecessary allocation.
>
> Example:
> >>> zipped = zip((1, 2, 3), (4, 5, 6))
> >>> zipped
> [(1, 4), (2, 5), (3, 6)]
> >>> dests = [[], []]
> >>> unzip_extend(dests, zipped)
> >>> dests
> [[1, 2, 3], [4, 5, 6]]
> """
> if len(zipped) < 1:
> raise ValueError, 'At least one item is required for unzip.'
> for index in range(len(zipped[0])):
> dests[index].extend(pair[index] for pair in zipped)
>
> This should perform pretty well, as extend with a comprehension is
> pretty fast. Not that it's truly meaningful, here's timeit on my 2GHz
> laptop:
>
> bash-3.1$ python -m timeit -s 'import unzip; zipped=zip(range(1024),
> range(1024))' 'unzip.unzip_extend([[], []], zipped)'
> 1000 loops, best of 3: 510 usec per loop
>
> By comparison, here's the unzip() version above:
>
> bash-3.1$ python -m timeit -s 'import unzip; zipped=zip(range(1024),
> range(1024))' 'unzip.unzip(zipped)'
> 1000 loops, best of 3: 504 usec per loop
>
> Rich
As Paddy wrote, zip is its own unzip:
>>> zipped = zip((1, 2, 3), (4, 5, 6))
>>> zipped
[(1, 4), (2, 5), (3, 6)]
>>> unzipped = zip(*zipped)
>>> unzipped
[(1, 2, 3), (4, 5, 6)]
Neat and completely confusing, huh? :-)
<http://paddy3118.blogspot.com/2007/02/unzip-un-needed-in-python.html>
--
More information about the Python-list
mailing list