不同数量元素的 Python 理解

问题描述 投票:0回答:1

一般问题

我有一个例子,我正在生成一个与输入源具有不同基数的元素理解。此基数不应是原始基数(数据驱动)的倍数,而应由条件引导。原始源中的某些元素可能会转换为目标中的一个元素,而其他元素可能会转换为多个元素,甚至没有。

现有方法

多个问题涉及相邻情况,但并不完全相同:

(顺便说一句,这两个问题不是彼此重复。它们解决的是不同的、甚至有些重叠的问题,尽管解决方案在一定程度上可以互换,但问题本身却不能互换。语言,亲爱的SO。)

第一个地址的理解的长度是源长度的精确倍数。第二种提供了一种通过

reduce
或通过理解本身的双重迭代从具有列表列表的结果生成平面列表的方法。请注意,在这种情况下,两者实际上都会产生不规则数量的元素(不是原始元素的倍数),但以数据驱动的方式,而不是条件驱动的方式。

简单的问题

我有一个字符串列表,其中包含一个数字或两个由连字符分隔的数字,比方说:

['1', '2', '2-3', '3-1', '4-5']

期望的结果是:

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

如您所见,基数没有关系(除了它增长)。

解决方案 1 — 糟糕

>>> a = ['1', '2', '2-3', '3-1', '4-5']
>>> '-'.join(a)
'1-2-2-3-3-1-4-5'
>>> '-'.join(a).split('-')
['1', '2', '2', '3', '3', '1', '4', '5']

这假设了两件事:

  1. 我正在使用列表。实际上,我的练习涉及字典、元组列表和此类配对数据集合。我可以加入其中一些组件,但我会完全失去与源数据其他部分的关系。
  2. 这很糟糕,丑陋而且可能效率低下。

解决方案 2 —
reduce

>>> a = ['1', '2', '2-3', '3-1', '4-5']
>>> reduce(lambda acc, elem: acc+elem, (x.split('-') for x in a))
['1', '2', '2', '3', '3', '1', '4', '5']

这个比前一个更好,但它仍然是数据驱动的。它也是列表列表的扁平化,尽管通过偷偷引入内部生成器而不是内部理解进行了稍微优化。

更复杂的问题

如果我只有一个数字列表并且我想根据值生成不同的响应长度怎么办?在这里,我将转向数字列表,以便不鼓励字符串操作响应。

现在,我想要一个结果列表,如果是奇数则放置数字,如果是偶数则放置数字及其一半:

>>> a = [1, 2, 3, 4, 5]
>>> # Magic code
[1, 1, 2, 3, 2, 4, 5]

因此,根据条件 -

x % 2 == 0
,在本例中 - 我想向列表中添加一个或两个数字。

解决方案 0 — 缺少旧的 C?

>>> a = [1, 2, 3, 4, 5]
>>> res = []
>>> for x in a:
...   if x % 2:
...     res.append(x)
...   else:
...     res.append(x//2)
...     res.append(x)
... 
>>> res
[1, 1, 2, 3, 2, 4, 5]

对该解决方案的侮辱包括“反Pythonic”、“丑陋的AF”,还有一些甚至更糟糕。它有效,但正如我常说的:“如果‘它有效’。”是你能对你的代码说的最好/唯一的好处......”

解决方案1——多维列表扁平化

>>> a = [1, 2, 3, 4, 5]
>>> [x if x % 2 else [x//2, x] for x in a]
[1, [1, 2], 3, [2, 4], 5]

现在我有一个包含元素和列表的列表。我的

reduce
会更复杂一点,所以我要把它们全部列出来:

>>> a = [1, 2, 3, 4, 5]
>>> [[x] if x % 2 else [x//2, x] for x in a]
[[1], [1, 2], [3], [2, 4], [5]]

现在我可以减少:

>>> a = [1, 2, 3, 4, 5]
>>> reduce(lambda acc, elem: acc+elem, ([x] if x % 2 else [x//2, x] for x in a))
[1, 1, 2, 3, 2, 4, 5]

再一次,可以工作,但不能直接工作。它仍然创建一个迭代来减少。

我需要一个解决方案,只需向目标提供根据每个源元素计算得出的可变数量的元素。之所以必须像表达式一样,是因为它嵌入到更广泛的表达式中。因此,尽管我非常尊重他们,但请不要提供 Kernighan 和 Ritchie 强制解决方案。

python list dictionary functional-programming list-comprehension
1个回答
0
投票

这是另一个解决方案

>>> from itertools import chain
>>> a = ['1', '2', '2-3', '3-1', '4-5']
>>> list(chain.from_iterable(item.split('-') for item in a))
['1', '2', '2', '3', '3', '1', '4', '5']
© www.soinside.com 2019 - 2024. All rights reserved.