How to print list of list into one single list in

2019-08-05 04:24发布

问题:

Today I had an interview and I was asked to print a list of list into one single list without using any for or while loop but you can use other built in function.

Here is the list:

>>> myList = [[[1,2,3],[4,5],[6,7,8,9]]]
>>> myList
[[[1, 2, 3], [4, 5], [6, 7, 8, 9]]]
>>>

The output will be [1, 2, 3, 4, 5, 6, 7, 8, 9].

Any idea how to go about this?

回答1:

Three options:

  1. You could sum the nested lists; sum() takes a second argument, a starting value, set that to an empty list:

    >>> sum(myList[0], [])
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    

    This works because sum() is essentially implemented as a loop:

     def sum(values, start=0):
         total = start
         for value in values:
             total += value
         return total
    

    which works with list concatenation, provided the start value is a list object itself. 0 + [1, 2, 3] would not work, but [] + [1, 2, 3] works just fine.

  2. You could use reduce() with operator.add(), which is essentially the same as sum(), minus the requirement to give a start value:

    from operator import add
    
    reduce(add, myList[0])
    

    operator.add() could be replaced with lambda a, b: a + b or with list.__add__ if imports are to be avoided at all cost.

    As the nested input list grows, operator.iadd() (in-place add, for lists the equivalent of list.extend()) will rapidly become a faster option:

    from operator import iadd
    
    reduce(add, myList[0], [])
    

    but this does need an empty list to start with.

  3. You could chain the lists using itertools.chain.from_iterable():

    >>> from itertools import chain
    >>> list(chain.from_iterable(myList[0]))
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    

All three solutions require that you use indexing to remove the outermost list, although you can also pass the one element in myList as a single argument to chain.from_iterable() with list(chain.from_iterable(*myList)) as well.

Of these options, reduce(add, ...) is the fastest:

>>> timeit.timeit("sum(myList[0], [])", 'from __main__ import myList')
1.2761731147766113
>>> timeit.timeit("reduce(add, myList[0])", 'from __main__ import myList; from operator import add')
1.0545191764831543
>>> timeit.timeit("reduce(lambda a, b: a.extend(b) or a, myList[0], [])", 'from __main__ import myList')
2.225532054901123
>>> timeit.timeit("list(chain.from_iterable(myList[0]))", 'from __main__ import myList; from itertools import chain')
2.0208170413970947

and comparing iadd versus add:

>>> timeit.timeit("reduce(add, myList[0])", 'from __main__ import myList; from operator import add')
0.9298770427703857
>>> timeit.timeit("reduce(iadd, myList[0], [])", 'from __main__ import myList; from operator import iadd')
1.178157091140747
>>> timeit.timeit("reduce(add, myListDoubled)", 'from __main__ import myList; myListDoubled = myList[0] + myList[0]; from operator import add')
2.3597090244293213
>>> timeit.timeit("reduce(iadd, myListDoubled, [])", 'from __main__ import myList; myListDoubled = myList[0] + myList[0]; from operator import iadd')
1.730151891708374

You could use recursion to avoid using a loop, to make this work for arbitrarily nested lists:

def flatten(lst):
    try:
        return flatten(sum(lst, []))
    except TypeError:
        return lst

Demo:

>>> flatten(myList)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> flatten(myList + myList)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]


回答2:

If we assume no imports allowed and that we are still on 2.7.x,

reduce(lambda x,y:x+y,*myList)

A quick search show that this question, making a flat list out of lists, has been analyzed in depth: Making a flat list out of list of lists in Python and although in that thread there is no restriction on what functions you can use, they answer goes into great detail about the time complexity of using different methods. This is quite important, as it could be the follow up question in an interview.



回答3:

myList = [[[1,2,3],[4,5],[6,7,8,9]]]

sum(myList[0], [])

Output

[1, 2, 3, 4, 5, 6, 7, 8, 9]


回答4:

Use itertools.chain.from_iterable:

In [34]: from itertools import chain

In [35]: list(chain.from_iterable(myList[0]))
Out[35]: [1, 2, 3, 4, 5, 6, 7, 8, 9]


回答5:

try this

import itertools

list(itertools.chain(*mylist))