【问题标题】:How to print list of list into one single list in python without using any for or while loop?python - 如何在不使用任何for或while循环的情况下将列表列表打印到python中的一个列表中?
【发布时间】:2013-12-05 14:26:16
【问题描述】:

今天我有一个面试,我被要求将一个列表打印到一个列表中,而不使用任何 for 或 while 循环,但你可以使用其他内置函数。

这里是列表:

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

输出将是[1, 2, 3, 4, 5, 6, 7, 8, 9]

知道该怎么做吗?

【问题讨论】:

  • 这很少见:你可以使用其他内置函数 ;-)
  • +1,@AshwiniChaudhary。另外,我很好奇这个问题的答案会给面试官带来什么。
  • 嗨 Ashwini,内置函数。
  • 是的,这是要求。因此,不允许使用 itertool,但允许 sum 和 reduce。

标签: python list iteration


【解决方案1】:

三个选项:

  1. 您可以对嵌套列表求和; sum() 接受第二个参数,一个起始值,将其设置为一个空列表:

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

    之所以有效,是因为sum() 本质上是作为循环实现的:

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

    它适用于列表连接,前提是起始值是列表对象本身。 0 + [1, 2, 3] 不起作用,但 [] + [1, 2, 3] 工作正常。

  2. 您可以将reduce()operator.add() 一起使用,这与sum() 基本相同,但需要提供起始值:

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

    如果要不惜一切代价避免导入,可以将operator.add() 替换为lambda a, b: a + blist.__add__

    随着嵌套输入列表的增长,operator.iadd()(就地添加,对于列表相当于list.extend())将迅速成为一个更快的选择:

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

    但这确实需要一个空列表才能开始。

  3. 您可以使用itertools.chain.from_iterable() 链接列表:

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

所有三种解决方案都要求您使用索引来删除最外层的列表,尽管您也可以将 myList 中的一个元素作为单个参数传递给 chain.from_iterable()list(chain.from_iterable(*myList))

在这些选项中,reduce(add, ...) 是最快的:

>>> 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

比较iaddadd

>>> 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

您可以使用递归来避免使用循环,以使其适用于任意嵌套的列表:

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

演示:

>>> 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]

【讨论】:

  • 对于这个列表,对于链式方法,可以使用 *myList 而不是 mylist[0]
  • 嗨 Martinjn,你能解释一下 sum 如何从 help(sum) 中解决这个问题 sum(...) sum(sequence[, start]) -> value 返回一个序列的总和数字(不是字符串)加上参数“开始”的值(默认为 0)。当序列为空时,返回start。
  • 使用 reduce(operator.iadd, lst[0], []) 使其成为线性 (O(n)-time) 而不是二次 (O(n**2)-time) 算法。提供初始值以避免就地更改lst
  • @J.F.Sebastian:哦,好点子。替代的非导入版本是lambda a, b: a.extend(b) or a
  • 如果不允许导入,您可以使用list.__iadd__ 代替operator.iadd
【解决方案2】:

如果我们假设不允许导入并且我们仍然在 2.7.x 上,

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

快速搜索表明,这个问题,从列表中制作一个平面列表,已经过深入分析:Making a flat list out of list of lists in Python 虽然在该线程中没有限制您可以使用哪些功能,但他们的回答非常详细关于使用不同方法的时间复杂度。这很重要,因为它可能是面试中的后续问题。

【讨论】:

  • 这是另一个很棒的答案,
  • 另外一个假设是在 Python2 上运行,因为在 Python3 中需要导入 reduce function
  • @Yeo 我不知道。很高兴知道。由于我正在使用一些科学工具,我仍在使用 2.7.x。
  • @yopy,如果我是你,我会投票给这个作为答案,原因如下:这是一个面试问题,在没有任何特定库的情况下回答这个问题更合适。 Reduce 不是一个库,而是一个原始的函数式编程。必须深入思考才能理解这是如何工作的。 :) +1
  • @Yeo gee 谢谢!函数式编程确实是一头奇怪而美丽的野兽。
【解决方案3】:
myList = [[[1,2,3],[4,5],[6,7,8,9]]]

sum(myList[0], [])

输出

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

【讨论】:

  • 哇,这就是我想要的 :) 他要我使用 sum :) 我在想如何使用 sum。
【解决方案4】:

使用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]

【讨论】:

  • 哦让我检查一下,不使用模块是否有任何其他内置函数来解决它。
  • @yopy Martijn 和 koffein 回答了那部分。
【解决方案5】:

试试这个

import itertools

list(itertools.chain(*mylist))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-12
    • 2019-01-18
    • 1970-01-01
    • 2015-04-24
    • 2017-03-05
    • 2018-03-18
    • 2023-02-26
    相关资源
    最近更新 更多