One-liner to merge lists?

Peter Otten __peter__ at web.de
Sun Feb 27 16:49:24 EST 2022


On 27/02/2022 17:28, Chris Angelico wrote:
> On Mon, 28 Feb 2022 at 03:24, MRAB <python at mrabarnett.plus.com> wrote:
>>
>> On 2022-02-27 08:51, Barry Scott wrote:
>>>
>>>
>>>> On 22 Feb 2022, at 09:30, Chris Angelico <rosuav at gmail.com> wrote:
>>>>
>>>> On Tue, 22 Feb 2022 at 20:24, Frank Millman <frank at chagford.com <mailto:frank at chagford.com>> wrote:
>>>>>
>>>>> Hi all
>>>>>
>>>>> I think this should be a simple one-liner, but I cannot figure it out.
>>>>>
>>>>> I have a dictionary with a number of keys, where each value is a single
>>>>> list -
>>>>>
>>>>>>>> d = {1: ['aaa', 'bbb', 'ccc'], 2: ['fff', 'ggg']}
>>>>>
>>>>> I want to combine all values into a single list -
>>>>>
>>>>>>>> ans = ['aaa', 'bbb', 'ccc', 'fff', 'ggg']
>>>>>
>>>>> I can do this -
>>>>>
>>>>>>>> a = []
>>>>>>>> for v in d.values():
>>>>> ...   a.extend(v)
>>>>> ...
>>>>>>>> a
>>>>> ['aaa', 'bbb', 'ccc', 'fff', 'ggg']
>>>>>
>>>>> I can also do this -
>>>>>
>>>>>>>> from itertools import chain
>>>>>>>> a = list(chain(*d.values()))
>>>>>>>> a
>>>>> ['aaa', 'bbb', 'ccc', 'fff', 'ggg']
>>>>>>>>
>>>>>
>>>>> Is there a simpler way?
>>>>>
>>>>
>>>> itertools.chain is a good option, as it scales well to arbitrary
>>>> numbers of lists (and you're guaranteed to iterate over them all just
>>>> once as you construct the list). But if you know that the lists aren't
>>>> too large or too numerous, here's another method that works:
>>>>
>>>>>>> sum(d.values(), [])
>>>> ['aaa', 'bbb', 'ccc', 'fff', 'ggg']
>>>>
>>>> It's simply adding all the lists together, though you have to tell it
>>>> that you don't want a numeric summation.
>>>
>>> If you code is performance sensitive do not use sum() as it creates lots of tmp list that are deleted.
>>>
>>> I have an outstanding ticket at work to replace all use of sum() on lists as when we profiled it
>>> stands out as a slow operation. We have a lots of list of list that we need to flatten.
>>>
>> I think that 'sum' uses '__add__' but not '__iadd__'.
>>
>> If it copied the given value, if present, and then used '__iadd__', if
>> present, wouldn't that speed it up?
>
> It's hardly relevant. If you care about speed, use chain(), like
> everyone's been saying all along :)

Not everyone. I believe (*) that __iadd__ is faster, and again, you can
spell it

functools.reduce(operator.iconcat, list_of_lists, [])

(*) Actual measurements left as an exercise ;)



More information about the Python-list mailing list