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