【问题标题】:Python:reduce list but keep detailsPython:减少列表但保留细节
【发布时间】:2012-08-28 11:15:51
【问题描述】:

假设我有一个项目列表,其中一些项目在某种程度上相似 但在一个点后相差一个数字

['abc.1',
 'abc.2',
 'abc.3',
 'abc.7',
 'xyz.1',
 'xyz.3',
 'xyz.11',
 'ghj.1',
 'thj.1']

我想从这个列表中生成一个新列表,它可以折叠多个但保留它们的一些数据,即数字后缀 所以上面的列表应该产生一个新的列表

[('abc',('1','2','3','7'))
 ('xyz',('1','3','11'))
 ('ghj',('1'))
 ('thj',('1'))]

我的想法是,第一个列表可以通过点分成对 但是然后我如何按第一部分对对进行分组而不丢失第二部分

对不起,如果这个问题很无聊,提前谢谢

... 哇,没想到这么快就有这么多好答案,谢谢

【问题讨论】:

  • 您的初始列表不是有效的 Python 代码。这些应该是字符串吗?
  • 是的,这些是字符串,我不是说它是代码,很抱歉造成混淆

标签: python list reduce


【解决方案1】:
from collections import defaultdict

d = defaultdict(list)

for el in elements:
    key, nr = el.split(".")
    d[key].append(nr)

#revert dict to list
newlist = d.items()

【讨论】:

  • +1:我认为这是一个很好的例子,直接迭代解决方案明显优于替代方案。
【解决方案2】:

使用分隔函数映射列表,使用带有第一个元素的键的itertools.groupby,并将第二个元素收集到结果中。

from itertools import groupby, imap

list1 = ["abc.1", "abc.2", "abc.3", "abc.7", "xyz.1", "xyz.3", "xyz.11", "ghj.1", "thj.1"]

def break_up(s):
    a, b = s.split(".")
    return a, int(b)

def prefix(broken_up): return broken_up[0]
def suffix(broken_up): return broken_up[1]

result = []
for key, sub in groupby(imap(break_up, list1), prefix):
    result.append((key, tuple(imap(suffix, sub))))

print result

输出:

[('abc', (1, 2, 3, 7)), ('xyz', (1, 3, 11)), ('ghj', (1,)), ('thj', (1,))]

【讨论】:

  • 请注意,与基于defaultdict 的解决方案不同,此解决方案不分配输入列表大小的额外存储空间。 (当然结果列表除外,但可以通过产生值而不是将它们附加到列表来轻松避免。)
  • 这是一个非常有趣的解决方案,我需要更多地了解函数式编程才能完全理解这个解决方案,
  • groupby(sequence, keyfun) 根据 keyfun 获取序列并按看起来相同的元素对其进行分组。您从中得到的是连续的(键,元素...)对。该解决方案使用imap 将列表元素分解为成分——前缀(第一个)和后缀(第二个)。然后它告诉groupby 按前缀对列表项进行分组,但保留所有后缀。尽管冗长,但这个解决方案似乎最接近原始问题的精神。
  • 我现在已经对代码进行了外观编辑,使其看起来不那么“实用”(没有 lambda),并改进了命名以使发生的事情更清楚。
  • 我想我现在明白了,我需要了解一下 itertools,它似乎是一个非常强大的工具。谢谢!
猜你喜欢
  • 2016-09-29
  • 2013-05-12
  • 1970-01-01
  • 1970-01-01
  • 2021-12-12
  • 2021-03-03
  • 1970-01-01
  • 2020-10-08
  • 2011-07-31
相关资源
最近更新 更多