One-liner to merge lists?

Peter Otten __peter__ at web.de
Wed Feb 23 06:18:19 EST 2022


On 22/02/2022 10:44, Frank Millman wrote:
> On 2022-02-22 11:30 AM, Chris Angelico wrote:
>> On Tue, 22 Feb 2022 at 20:24, Frank Millman <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.
>>
>
> Thanks, that is neat.
>
> However, I did see this -
>
>  >>> help(sum)
> Help on built-in function sum in module builtins:
>
> sum(iterable, /, start=0)
>      Return the sum of a 'start' value (default: 0) plus an iterable of
> numbers
>
>      When the iterable is empty, return the start value.
>      This function is intended specifically for use with numeric values
> and may reject non-numeric types.
>  >>>
>
> So it seems that it is not recommended.

If you don't like the idea of 'adding' strings you can 'concat'enate:

 >>> items = [[1,2,3], [4,5], [6]]
 >>> functools.reduce(operator.concat, items)
[1, 2, 3, 4, 5, 6]
 >>> functools.reduce(operator.iconcat, items, [])
[1, 2, 3, 4, 5, 6]

The latter is the functional way to spell your for... extend() loop.
Don't forget to provide the initial value in that case lest you modify
the input:

 >> functools.reduce(operator.iconcat, items)  # wrong
[1, 2, 3, 4, 5, 6]
 >>> items
[[1, 2, 3, 4, 5, 6], [4, 5], [6]]  # oops




More information about the Python-list mailing list