interleaving dictionary values

J

j1o1h1n

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(None, [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, ltypes)):
l[i:i+1] = list(l)
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(None, 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..."
 
R

Roberto Bonvallet

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(None, 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 :)
.... 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,
 
N

Neil Cerutti

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(None, flatten(map(None, [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.
[(1, 7, 4), (2, 8, 5), (3, 9, None)]
So... my bit of code becomes:
[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:
[1, 2, 3, 7, 8, 9, 4, 5]
 
B

bearophileHUGS

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.itervalues()) )

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

Bye,
bearophile
 
N

Noah Rawlins

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, ltypes)):
l[i:i+1] = list(l)
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...
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(isinstance(l, ltypes)):
l[i:i+1] = list(l)
i += 1
except IndexError:
pass
return l

noah
 
T

Tuomas

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(None, [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, ltypes)):
l[i:i+1] = list(l)
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(None, 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..."


What about:
>>> 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.extend, d.values()) [None, None, None]
>>> L
[1, 2, 3, 7, 8, 9, 4, 5]

TV
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top