473,993 Members | 3,714 Online

# interleaving dictionary values

Hello,

I was trying to create a flattened list of dictionary values where each
value is a list, and I was hoping to do this in some neat functionally
style, in some brief, throwaway line so that it would assume the
insignificance that it deserves in the grand scheme of my program.

I had in mind something like this:
>>interleave([1, 2, 3], [4,5], [7, 8, 9])
[1, 4, 7, 2, 5, 8, 3, 9]

I played for a while with zip(), [some newfangled python keyword, that
I was truly shocked to find has been hiding at the bottom of the list
built in functions since version 2.0], before giving up and going back
to trusty old map(), long celebrated for making code hard to read:
>>map(None, [1, 2, 3], [4,5], [7, 8, 9])
[(1, 4, 7), (2, 5, 8), (3, None, 9)]

This is basically it. It then becomes:
>>filter(None , flatten(map(Non e, [1, 2, 3], [4,5], [7, 8, 9])))
[1, 4, 7, 2, 5, 8, 3, 9]

filter(None, - my brain parses that automatically now. This is not so
bad. Flatten is snitched from ASPN/Cookbook/Python/Recipe/363051,
thank you Jordan Callicoat, Mike C. Fletcher:

def flatten(l, ltypes=(list, tuple)):
i = 0
while (i < len(l)):
while (isinstance(l[i], ltypes)):
l[i:i+1] = list(l[i])
i += 1
return l

Trouble is then getting map() to play with the result of dict.values().
I only worked this out while writing this post, of course.

Given a dictionary like d = { "a" : [1, 2, 3], "b" : [4, 5], "c" : [7,
8, 9]} - I was hoping to do this:

map(None, d.values())

But instead I (finally worked out I could) do this:

apply(map, tuple([None] + d.values()))

So... my bit of code becomes:

filter(None, flatten(map(Non e, apply(map, tuple([None] +
d.values())))))

It fits on one line, but it feels far more evil than I set out to be.
The brackets at the end are bad for my epilepsy.

Surely there is there some nice builtin function I have missed?

--
| John J. Lehmann, j1o1h1n(@)gmail .com
+ [lost-in-translation] "People using public transport look stern, and
handbag
+ snatchers increase the ill feeling." A Japanese woman, Junko, told
the paper:
+ "For us, Paris is the dream city. The French are all beautiful and
elegant
+ And then, when we arrive..."

Nov 21 '06 #1
5 1981
j1*****@gmail.c om wrote:
[...]
I had in mind something like this:
>>>interleave ([1, 2, 3], [4,5], [7, 8, 9])
[1, 4, 7, 2, 5, 8, 3, 9]
[...]
But instead I (finally worked out I could) do this:

apply(map, tuple([None] + d.values()))
apply is deprecated, it should be map(None, *d.values())
So... my bit of code becomes:

filter(None, flatten(map(Non e, apply(map, tuple([None] +
d.values())))))

It fits on one line, but it feels far more evil than I set out to be.
The brackets at the end are bad for my epilepsy.

Surely there is there some nice builtin function I have missed?
You have missed the "it doesn't need to be a one-liner" motto :)
>>def interleave(*arg s):
.... result = []
.... for items in map(None, *args):
.... result.extend([x for x in items if x is not None])
.... return result
....
>>interleave([1, 2, 3], [4,5], [7, 8, 9])
[1, 4, 7, 2, 5, 8, 3, 9]

Cheers,
--
Roberto Bonvallet
Nov 21 '06 #2
On 2006-11-21, j1*****@gmail.c om <j1*****@gmail. comwrote:
I had in mind something like this:
>>>interleave ([1, 2, 3], [4,5], [7, 8, 9])
[1, 4, 7, 2, 5, 8, 3, 9]

[...] before giving up and going back to trusty old map(), long
celebrated for making code hard to read:
>>>map(None, [1, 2, 3], [4,5], [7, 8, 9])
[(1, 4, 7), (2, 5, 8), (3, None, 9)]

This is basically it. It then becomes:
>>>filter(Non e, flatten(map(Non e, [1, 2, 3], [4,5], [7, 8, 9])))
[1, 4, 7, 2, 5, 8, 3, 9]
You can use itertools.chain instead of flatten:
>>from itertools import chain
filter(None , chain(*map(None , [1, 2, 3], [4, 5], [7, 8, 9])))
[1, 4, 7, 2, 5, 8, 3, 9]
Trouble is then getting map() to play with the result of dict.values().
I only worked this out while writing this post, of course.

Given a dictionary like d = { "a" : [1, 2, 3], "b" : [4, 5], "c" : [7,
8, 9]} - I was hoping to do this:

map(None, d.values())
You need the * to "unpack" the list. It has generally taken the
place of apply.
>>map(None, *d.values())
[(1, 7, 4), (2, 8, 5), (3, 9, None)]
So... my bit of code becomes:
>>filter(None , chain(*map(None , *d.values())))
[1, 7, 4, 2, 8, 5, 3, 9]

I don't think that the specific ordering that's achieved has any
valuable significance. You might be just as happy with the
simpler:
>>list(chain(*d .values()))
[1, 2, 3, 7, 8, 9, 4, 5]

--
Neil Cerutti
Weight Watchers will meet at 7 p.m. Please use large double door at the side
entrance. --Church Bulletin Blooper
Nov 21 '06 #3
d = {"a": [1, 2, 3], "b": [4, 5], "c": [7, 8, 9]}

# Simple solution:
result = []
for l in d.itervalues():
result.extend(l )
print result

# Alternative:
from itertools import chain
print list( chain(*d.iterva lues()) )

I don't know what's the faster solution, the first one seem more
readable and it's probably fast enough.

Bye,
bearophile

Nov 21 '06 #4
j1*****@gmail.c om wrote:
filter(None, - my brain parses that automatically now. This is not so
bad. Flatten is snitched from ASPN/Cookbook/Python/Recipe/363051,
thank you Jordan Callicoat, Mike C. Fletcher:

def flatten(l, ltypes=(list, tuple)):
i = 0
while (i < len(l)):
while (isinstance(l[i], ltypes)):
l[i:i+1] = list(l[i])
i += 1
return l
On a side note, that version of flatten doesn't handle an empty list as
the last element of a list...
>>flatten([1, 2, 3, []])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in flatten
IndexError: list index out of range

You need a try: in there or something...

def flatten(l, ltypes=(list, tuple)):
i = 0
while(i < len(l)):
try:
while(isinstanc e(l[i], ltypes)):
l[i:i+1] = list(l[i])
i += 1
except IndexError:
pass
return l

noah
Nov 22 '06 #5
j1*****@gmail.c om wrote:
Hello,

I was trying to create a flattened list of dictionary values where each
value is a list, and I was hoping to do this in some neat functionally
style, in some brief, throwaway line so that it would assume the
insignificance that it deserves in the grand scheme of my program.

I had in mind something like this:

>>>>interleav e([1, 2, 3], [4,5], [7, 8, 9])

[1, 4, 7, 2, 5, 8, 3, 9]

I played for a while with zip(), [some newfangled python keyword, that
I was truly shocked to find has been hiding at the bottom of the list
built in functions since version 2.0], before giving up and going back
to trusty old map(), long celebrated for making code hard to read:

>>>>map(None, [1, 2, 3], [4,5], [7, 8, 9])

[(1, 4, 7), (2, 5, 8), (3, None, 9)]

This is basically it. It then becomes:

>>>>filter(None , flatten(map(Non e, [1, 2, 3], [4,5], [7, 8, 9])))

[1, 4, 7, 2, 5, 8, 3, 9]

filter(None, - my brain parses that automatically now. This is not so
bad. Flatten is snitched from ASPN/Cookbook/Python/Recipe/363051,
thank you Jordan Callicoat, Mike C. Fletcher:

def flatten(l, ltypes=(list, tuple)):
i = 0
while (i < len(l)):
while (isinstance(l[i], ltypes)):
l[i:i+1] = list(l[i])
i += 1
return l

Trouble is then getting map() to play with the result of dict.values().
I only worked this out while writing this post, of course.

Given a dictionary like d = { "a" : [1, 2, 3], "b" : [4, 5], "c" : [7,
8, 9]} - I was hoping to do this:

map(None, d.values())

But instead I (finally worked out I could) do this:

apply(map, tuple([None] + d.values()))

So... my bit of code becomes:

filter(None, flatten(map(Non e, apply(map, tuple([None] +
d.values())))))

It fits on one line, but it feels far more evil than I set out to be.
The brackets at the end are bad for my epilepsy.

Surely there is there some nice builtin function I have missed?

--
| John J. Lehmann, j1o1h1n(@)gmail .com
+ [lost-in-translation] "People using public transport look stern, and
handbag
+ snatchers increase the ill feeling." A Japanese woman, Junko, told
the paper:
+ "For us, Paris is the dream city. The French are all beautiful and
elegant
+ And then, when we arrive..."
>>d = { "a" : [1, 2, 3], "b" : [4, 5], "c" : [7, 8, 9]}
L=[]
for x in d.values(): L.extend(x)
....
>>L
[1, 2, 3, 7, 8, 9, 4, 5]

or a little curious:
>>L=[]
map(L.exten d, d.values())
[None, None, None]
>>L
[1, 2, 3, 7, 8, 9, 4, 5]

TV

Nov 22 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.