peixe
peixe

Reputation: 1292

Zip string-subset from tuples in a list

With a structure like this

hapts = [('1|2', '1|2'), ('3|4', '3|4')]

I need to zip it (sort of...) to get the following:

end = ['1|1', '2|2', '3|3', '4|4']

I started working with the following code:

zipped=[] 
for i in hapts:    
    tete = zip(i[0][0], i[1][0]) 
    zipped.extend(tete)
    some = zip(i[0][2], i[1][2])
    zipped.extend(some)        

... and got it zipped like this:

zipped = [('1', '1'), ('2', '2'), ('3', '3'), ('4', '4')]

Any suggestions on how to continue? Furthermore i'm sure there should a more elegant way to do this, but is hard to pass to Google an accurate definition of the question ;) Thx!

Upvotes: 1

Views: 1120

Answers (4)

Gareth Latty
Gareth Latty

Reputation: 88997

You are very close to solving this, I would argue the best solution here is a simple str.join() in a list comprehension:

["|".join(values) for values in zipped]

This also has the bonus of working nicely with (potentially) more values, without modification.

If you wanted tuples (which is not what your requested output shows, as brackets don't make a tuple, a comma does), then it is trivial to add that in:

[("|".join(values), ) for values in zipped]

Also note that zipped can be produced more effectively too:

>>> zipped = itertools.chain.from_iterable(zip(*[part.split("|") for part in group]) for group in hapts)
>>> ["|".join(values) for values in zipped]
['1|1', '2|2', '3|3', '4|4']

And to show what I meant before about handling more values elegantly:

>>> hapts = [('1|2|3', '1|2|3', '1|2|3'), ('3|4|5', '3|4|5', '3|4|5')]
>>> zipped = itertools.chain.from_iterable(zip(*[part.split("|") for part in group]) for group in hapts)
>>> ["|".join(values) for values in zipped]
['1|1|1', '2|2|2', '3|3|3', '3|3|3', '4|4|4', '5|5|5']

Upvotes: 3

Silas Ray
Silas Ray

Reputation: 26160

end = []
for groups in hapts:
    end.extend('|'.join(regrouped) for regrouped in zip([group.split('|') for group in groups]))

This should also continue to work with n-length groups of n-length pipe-delimited characters, and n-length groups of groups, though it will truncate the regrouped values to the shortest group of characters in each group of character groups.

Upvotes: 0

Abhijit
Abhijit

Reputation: 63727

The problem in this context is to

  • unfold the list
  • reformat it
  • fold it

Here is how you may approach the problem

>>> reformat = lambda t: map('|'.join,  izip(*(e.split("|") for e in  t)))
>>> list(chain(*(reformat(t) for t in hapts)))
['1|1', '2|2', '3|3', '4|4']

You don't need the working code in this context

Instead if you need to work on your output, just rescan it and join it with "|"

>>> ['{}|{}'.format(*t) for t in zipped]
['1|1', '2|2', '3|3', '4|4']

Note

Parenthesis are redundant in your output

Upvotes: 1

Katriel
Katriel

Reputation: 123632

Your code basically works, but here's a more elegant way to do it.

First define a transposition function that takes an entry of hapts and flips it:

>>> transpose = lambda tup: zip(*(y.split("|") for y in tup))

Then map that function over hapts:

>>> map(transpose, hapts)
... [[('1', '1'), ('2', '2')], [('3', '3'), ('4', '4')]]

and then if you want to flatten this into one list

>>> y = list(chain.from_iterable(map(transpose, hapts)))
... [('1', '1'), ('2', '2'), ('3', '3'), ('4', '4')]

Finally, to join it back up into strings again:

>>> map("|".join, y)
... ['1|1', '2|2', '3|3', '4|4']

Upvotes: 0

Related Questions