【问题标题】:Alternative ways for iterator chaining in List Comprehension?列表理解中迭代器链接的替代方法?
【发布时间】:2021-01-11 18:31:30
【问题描述】:

我想在列表理解中将两个或多个不同的迭代器链接在一起。

假设我想将大写和小写字母组合成一个列表。我原来的方式是这样的,

lst1 = [chr(i) for i in range(97,123)]
lst2 = [chr(i) for i in range(65,91)]
lst = lst1+lst2

但是我认为必须有一些其他方法可以在一行中很好地做到这一点,然后我将它与 itertools 模块一起使用,

lst = [chr(i) for i in itertools.chain(range(97,123), range(65,91))]

最后我也想到了元组拆包,

lst = [chr(i) for i in (*range(97,123), *range(65,91))]

与其他两种方法相比,Itertools 速度较慢(元组解包是最快的一种)

例如,第一个范围和第二个范围内的字符组成列表

>>> lst1
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

>>> lst2
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

我希望它们仅与 1 个迭代器合并,而不是两个单独的迭代器。下面给出了合并列表的示例,其中使用了 2 个不同范围的值,

>>> lst
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']

有什么办法可以改进或改变设计吗?

【问题讨论】:

  • 您是否尝试过itertools.chain 两个生成器而不是范围? list(itertools.chain((chr(i) for i in range(97, 123)), (chr(i) for i in range(65, 91))))
  • 您能否提供一个示例输出,以便我们准确了解您正在寻找什么解决方案?

标签: python list iterator list-comprehension


【解决方案1】:

您找到了正确的解决方案。

注意:itertools.chain 可能会稍微慢一些,但它的优点是(有效地)零内存开销,我一般会推荐它。 range 已经(实际上)是零内存开销,因此将它与 chain 一起使用意味着根本没有有意义的内存开销,而使用解包到 tuple 涉及将 ranges 都实现为 tuple原因。如果大小永远不会增加,那么无论如何,但如果输入可能是可变长度的,chain 比在内存中实现无限迭代更安全。

当然,对于您的具体情况,显而易见的解决方案(更易读)是:

 import string

 lst = list(string.ascii_letters)

【讨论】:

  • +1 表示提供相同字母顺序的替代方式(大写字母在最后,尽管数值较小)。我完全希望list(string.ascii_letters) 以相反的方式订购。
  • @Adirio:其实我也是;最初我将它写成string.ascii_lowercasestring.ascii_uppercase 的串联,然后意识到ascii_letters 的顺序已经正确。 :-)
【解决方案2】:

这可能不如从包string 中提取的列表那么整洁,但它确实通过将两个集合合并创建一个可迭代来解决您的问题,并且应该也非常有效。

>>> [chr(i) for i in set(range(97,123)).union(range(65,91))]
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

【讨论】:

  • 三个注意事项: 1. 依靠sets 来保持顺序是一个糟糕的想法(碰巧,这会产生错误的顺序,将大写放在第一位,尽管有点令人惊讶的是所有字母都是否则按顺序)。 2. 不需要将union的参数转换成set;它接受任意迭代(如果您使用| 进行联合,则需要两者都是sets,但命名方法不是特定的)。 3. 在这里使用sets 并没有比仅仅连接ranges 更有意义的好处;将两个 ranges 解包到一个 tuple 可以更快地获得一个集合。
  • 嘿,感谢您的启发!学到了很多:D
猜你喜欢
  • 2020-01-13
  • 1970-01-01
  • 2021-01-07
  • 2018-04-26
  • 2022-10-15
  • 2019-01-03
  • 2020-12-03
  • 1970-01-01
  • 2021-02-08
相关资源
最近更新 更多