如何使用列表理解将元组的元组转换为一维列表?

发布于 2024-09-08 19:47:59 字数 653 浏览 11 评论 0原文

我有一个元组的元组 - 例如:

tupleOfTuples = ((1, 2), (3, 4), (5,))

我想将其转换为按顺序排列的所有元素的平面一维列表:

[1, 2, 3, 4, 5]

我一直在尝试通过列表理解来完成此任务。但我似乎无法弄清楚。我能够通过 for-each 循环来完成它:

myList = []
for tuple in tupleOfTuples:
   myList = myList + list(tuple)

但我觉得必须有一种方法可以通过列表理解来做到这一点。

一个简单的 [list(tuple) for tupleOfTuples] 只是为您提供一个列表列表,而不是单个元素。我想我也许可以在此基础上使用解包运算符来解包列表,如下所示:

[*list(tuple) for tuple in tupleOfTuples]

[*(list(tuple)) for tuple in tupleOfTuples]

... 但这不起作用。有什么想法吗?或者我应该坚持循环?

I have a tuple of tuples - for example:

tupleOfTuples = ((1, 2), (3, 4), (5,))

I want to convert this into a flat, one-dimensional list of all the elements in order:

[1, 2, 3, 4, 5]

I've been trying to accomplish this with list comprehension. But I can't seem to figure it out. I was able to accomplish it with a for-each loop:

myList = []
for tuple in tupleOfTuples:
   myList = myList + list(tuple)

But I feel like there must be a way to do this with a list comprehension.

A simple [list(tuple) for tuple in tupleOfTuples] just gives you a list of lists, instead of individual elements. I thought I could perhaps build on this by using the unpacking operator to then unpack the list, like so:

[*list(tuple) for tuple in tupleOfTuples]

or

[*(list(tuple)) for tuple in tupleOfTuples]

... but that didn't work. Any ideas? Or should I just stick to the loop?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

停顿的约定 2024-09-15 19:47:59

它通常被称为展平嵌套结构。

>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> [element for tupl in tupleOfTuples for element in tupl]
[1, 2, 3, 4, 5]

只是为了演示效率:

>>> import timeit
>>> it = lambda: list(chain(*tupleOfTuples))
>>> timeit.timeit(it)
2.1475738355700913
>>> lc = lambda: [element for tupl in tupleOfTuples for element in tupl]
>>> timeit.timeit(lc)
1.5745135182887857

ETA:请不要使用tuple作为变量名,它会隐藏内置变量。

it's typically referred to as flattening a nested structure.

>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> [element for tupl in tupleOfTuples for element in tupl]
[1, 2, 3, 4, 5]

Just to demonstrate efficiency:

>>> import timeit
>>> it = lambda: list(chain(*tupleOfTuples))
>>> timeit.timeit(it)
2.1475738355700913
>>> lc = lambda: [element for tupl in tupleOfTuples for element in tupl]
>>> timeit.timeit(lc)
1.5745135182887857

ETA: Please don't use tuple as a variable name, it shadows built-in.

半葬歌 2024-09-15 19:47:59

如果您没有很多元组,只需使用 sum 即可。

>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> sum(tupleOfTuples, ())
(1, 2, 3, 4, 5)
>>> list(sum(tupleOfTuples, ())) # if you really need a list
[1, 2, 3, 4, 5]

如果您确实有很多元组,请使用 列表理解chain.from_iterable 以防止 sum 的二次行为。


微基准测试:

  • Python 2.6

    • 短元组的长元组

      $ python2.6 -m timeit -s 'tot = ((1, 2), )*500' '[tot 中 tupl 的元素 for tupl 中的元素]'
      10000 个循环,3 次最佳:每个循环 134 usec
      $ python2.6 -m timeit -s 'tot = ((1, 2), )*500' '列表(sum(tot, ()))'
      1000 个循环,3 个循环中最好的:每个循环 1.1 毫秒
      $ python2.6 -m timeit -s 'tot = ((1, 2), )*500;来自 itertools 导入链; ci = chain.from_iterable' '列表(ci(tot))'
      10000 个循环,3 次最佳:每个循环 60.1 usec
      $ python2.6 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain' 'list(chain(*tot))'
      10000 个循环,3 个循环中最好的:每个循环 64.8 usec
      
    • 长元组的短元组

      $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500)' '[tot 中 tupl 的元素 for tupl 中的元素]'
      10000 个循环,3 次最佳:每个循环 65.6 usec
      $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500)' 'list(sum(tot, ()))'
      100000 个循环,3 个循环中最好的:每个循环 16.9 usec
      $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500);来自 itertools 导入链; ci = chain.from_iterable' '列表(ci(tot))'
      10000 个循环,3 次最佳:每个循环 25.8 usec
      $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain' 'list(chain(*tot))'
      10000 个循环,3 个循环中最好的:每个循环 26.5 usec
      
  • Python 3.1

    • 短元组的长元组

      $ python3.1 -m timeit -s 'tot = ((1, 2), )*500' '[tot 中 tupl 的元素 for tupl 中的元素]'
      10000 个循环,3 个循环中最好的:每个循环 121 usec
      $ python3.1 -m timeit -s 'tot = ((1, 2), )*500' 'list(sum(tot, ()))'
      1000 个循环,3 个循环中最好的:每个循环 1.09 毫秒
      $ python3.1 -m timeit -s 'tot = ((1, 2), )*500;来自 itertools 导入链; ci = chain.from_iterable' '列表(ci(tot))'
      10000 个循环,3 个循环中最好的:每个循环 59.5 usec
      $ python3.1 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain' 'list(chain(*tot))'
      10000 个循环,3 次最佳:每个循环 63.2 usec
      
    • 长元组的短元组

      $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500)' '[tot 中 tupl 的元素 for tupl 中的元素]'
      10000 个循环,3 次最佳:每个循环 66.1 usec
      $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500)' 'list(sum(tot, ()))'
      100000 次循环,3 次最佳:每个循环 16.3 usec
      $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500);来自 itertools 导入链; ci = chain.from_iterable' '列表(ci(tot))'
      10000 个循环,3 个循环中最好的:每个循环 25.4 usec
      $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain' 'list(chain(*tot))'
      10000 个循环,3 个循环中最好的:每个循环 25.6 usec
      

观察:

  • 如果外部元组较短,sum 会更快。
  • 如果外部元组很长,list(chain.from_iterable(x)) 会更快。

Just use sum if you don't have a lot of tuples.

>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> sum(tupleOfTuples, ())
(1, 2, 3, 4, 5)
>>> list(sum(tupleOfTuples, ())) # if you really need a list
[1, 2, 3, 4, 5]

If you do have a lot of tuples, use list comprehension or chain.from_iterable to prevent the quadratic behavior of sum.


Micro-benchmarks:

  • Python 2.6

    • Long tuple of short tuples

      $ python2.6 -m timeit -s 'tot = ((1, 2), )*500' '[element for tupl in tot for element in tupl]'
      10000 loops, best of 3: 134 usec per loop
      $ python2.6 -m timeit -s 'tot = ((1, 2), )*500' 'list(sum(tot, ()))'
      1000 loops, best of 3: 1.1 msec per loop
      $ python2.6 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain; ci = chain.from_iterable' 'list(ci(tot))'
      10000 loops, best of 3: 60.1 usec per loop
      $ python2.6 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain' 'list(chain(*tot))'
      10000 loops, best of 3: 64.8 usec per loop
      
    • Short tuple of long tuples

      $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500)' '[element for tupl in tot for element in tupl]'
      10000 loops, best of 3: 65.6 usec per loop
      $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500)' 'list(sum(tot, ()))'
      100000 loops, best of 3: 16.9 usec per loop
      $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain; ci = chain.from_iterable' 'list(ci(tot))'
      10000 loops, best of 3: 25.8 usec per loop
      $ python2.6 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain' 'list(chain(*tot))'
      10000 loops, best of 3: 26.5 usec per loop
      
  • Python 3.1

    • Long tuple of short tuples

      $ python3.1 -m timeit -s 'tot = ((1, 2), )*500' '[element for tupl in tot for element in tupl]'
      10000 loops, best of 3: 121 usec per loop
      $ python3.1 -m timeit -s 'tot = ((1, 2), )*500' 'list(sum(tot, ()))'
      1000 loops, best of 3: 1.09 msec per loop
      $ python3.1 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain; ci = chain.from_iterable' 'list(ci(tot))'
      10000 loops, best of 3: 59.5 usec per loop
      $ python3.1 -m timeit -s 'tot = ((1, 2), )*500; from itertools import chain' 'list(chain(*tot))'
      10000 loops, best of 3: 63.2 usec per loop
      
    • Short tuple of long tuples

      $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500)' '[element for tupl in tot for element in tupl]'
      10000 loops, best of 3: 66.1 usec per loop
      $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500)' 'list(sum(tot, ()))'
      100000 loops, best of 3: 16.3 usec per loop
      $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain; ci = chain.from_iterable' 'list(ci(tot))'
      10000 loops, best of 3: 25.4 usec per loop
      $ python3.1 -m timeit -s 'tot = ((1, )*500, (2, )*500); from itertools import chain' 'list(chain(*tot))'
      10000 loops, best of 3: 25.6 usec per loop
      

Observation:

  • sum is faster if the outer tuple is short.
  • list(chain.from_iterable(x)) is faster if the outer tuple is long.
当梦初醒 2024-09-15 19:47:59

您将元组链接在一起:

from itertools import chain
print list(chain(*listOfTuples))

如果您熟悉 itertools,那么应该非常容易阅读,并且如果没有显式的 list,您甚至可以得到生成器形式的结果。

You're chaining the tuples together:

from itertools import chain
print list(chain(*listOfTuples))

Should be pretty readable if you're familiar with itertools, and without the explicit list you even have your result in generator form.

北渚 2024-09-15 19:47:59

我喜欢在这种情况下使用“reduce”(这就是“reduce”的用途!)

lot = ((1, 2), (3, 4), (5,))
print list(reduce(lambda t1, t2: t1 + t2, lot))

 > [1,2,3,4,5]

I like using 'reduce' in this situation (this is what reduce made for!)

lot = ((1, 2), (3, 4), (5,))
print list(reduce(lambda t1, t2: t1 + t2, lot))

 > [1,2,3,4,5]
荒岛晴空 2024-09-15 19:47:59

这些答案中的大多数仅适用于单一级别的扁平化。如需更全面的解决方案,请尝试此(来自 http://rightfootin .blogspot.com/2006/09/more-on-python-flatten.html):

def flatten(l, ltypes=(list, tuple)):
    ltype = type(l)
    l = list(l)
    i = 0
    while i < len(l):
        while isinstance(l[i], ltypes):
            if not l[i]:
                l.pop(i)
                i -= 1
                break
            else:
                l[i:i + 1] = l[i]
        i += 1
    return ltype(l)

Most of these answers will only work for a single level of flattening. For a more comprehensive solution, try this (from http://rightfootin.blogspot.com/2006/09/more-on-python-flatten.html):

def flatten(l, ltypes=(list, tuple)):
    ltype = type(l)
    l = list(l)
    i = 0
    while i < len(l):
        while isinstance(l[i], ltypes):
            if not l[i]:
                l.pop(i)
                i -= 1
                break
            else:
                l[i:i + 1] = l[i]
        i += 1
    return ltype(l)
梦里人 2024-09-15 19:47:59

使用 itertools.chain 的另一个解决方案

>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> from itertools import chain
>>> [x for x in chain.from_iterable(tupleOfTuples)]
[1, 2, 3, 4, 5]

Another solution using itertools.chain

>>> tupleOfTuples = ((1, 2), (3, 4), (5,))
>>> from itertools import chain
>>> [x for x in chain.from_iterable(tupleOfTuples)]
[1, 2, 3, 4, 5]
绅刃 2024-09-15 19:47:59

对于多级且可读的代码:

def flatten(bla):
    output = []
    for item in bla:
        output += flatten(item) if hasattr (item, "__iter__") or hasattr (item, "__len__") else [item]
    return output

我无法将其放在一行中(并且即使到目前为止仍保持可读)

For multilevel, and readable code:

def flatten(bla):
    output = []
    for item in bla:
        output += flatten(item) if hasattr (item, "__iter__") or hasattr (item, "__len__") else [item]
    return output

I could not get this to fit in one line (and remain readable, even by far)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文