I had to think about it too, David.

Renaming it lets it make a bit more sense:

[item for sublist in d.values() for item in sublist]

This spells it out for me that you are taking one list within the main list at 
a time and then taking one item at a time from the list. Since the nesting is 
consistent in this case it makes sense.

Sadly, I could break it easily by just adding a non-list item like this:

d = {1: ['aaa', 'bbb', 'ccc'], 2: ['fff', 'ggg'], 3: 666}

And, of course, if you nest it any deeper, it is not completely flattened.

Chris makes the point that using the chain version may be better as it is 
compiled in C. Really? I would prefer a solution that even if slower, is more 
robust. Is there some function already written that will flatten what is given 
to it by checking the type of what is supplied, and based on the type, 
returning any simple objects like numbers or a character string, and converting 
many other composite things to something like a list and after popping off an 
entry, calling itself recursively on the rest until the list is empty? 

This would be a good start:

def flatten2list(object):
    gather = []
    for item in object:
        if isinstance(item, (list, tuple, set)):
            gather.extend(flatten2list(item))            
        else:
            gather.append(item)
    return gather

Of course I had to call the above as:

flatten2list(d.values())
['aaa', 'bbb', 'ccc', 'fff', 'ggg']

Here is a more complex version of the dictionary:

d = {1: ['aaa', 'bbb', 'ccc'], 2: [['fff', ['ggg']]], 3: 666, 4: set(["a", "e", 
"i", "o", "u"])}
d.values()
dict_values([['aaa', 'bbb', 'ccc'], [['fff', ['ggg']]], 666, {'e', 'u', 'a', 
'o', 'i'}])

flatten2list(d.values())

['aaa', 'bbb', 'ccc', 'fff', 'ggg', 666, 'e', 'u', 'a', 'o', 'i']


The quest for a one-liner sometimes forgets that a typical function call is 
also a one-liner, with the work hidden elsewhere, often in a module written in 
python or mainly in C and so on. I suspect much more detailed functions like 
the above are available with a little search that handle more including just 
about any iterable that terminates.


-----Original Message-----
From: Dan Stromberg <drsali...@gmail.com>
To: David Raymond <david.raym...@tomtom.com>
Cc: python-list@python.org <python-list@python.org>
Sent: Tue, Feb 22, 2022 11:02 pm
Subject: Re: One-liner to merge lists?


On Tue, Feb 22, 2022 at 7:46 AM David Raymond <david.raym...@tomtom.com>
wrote:

> > Is there a simpler way?
>
> >>> d = {1: ['aaa', 'bbb', 'ccc'], 2: ['fff', 'ggg']}
> >>> [a for b in d.values() for a in b]
> ['aaa', 'bbb', 'ccc', 'fff', 'ggg']
> >>>
>

I like that way best.

But I'd still:
1) use a little more descriptive identifiers
2) put it in a function with a descriptive name
3) give the function a decent docstring

-- 
https://mail.python.org/mailman/listinfo/python-list

-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to