【问题标题】:Reduce list of lists if entries match如果条目匹配,则减少列表列表
【发布时间】:2015-04-29 10:55:34
【问题描述】:

我在 python 中有一个列表,看起来像

[['boy','121','is a male child'],['boy','121','is male'],['boy','121','is a child'],['girl','122','is a female child'],['girl','122','is a child']]

我想根据每个列表中的前 2 个条目来减少列表,得到

[['boy','121',is a male child, is male, is a child'],['girl','122','is a female child','is a child']]

有没有办法在不创建虚拟列表的情况下有效地做到这一点?

【问题讨论】:

  • 我不认为列表的列表是最好的结构。为什么不使用 {('boy', 121): ['is a male child', 'is male', 'is a child'], ...} 之类的东西?
  • 这也很好,只是我从索引搜索中获得了第一种格式,并想根据第一个 2 个条目是否匹配来减少它——如果这有意义吗?
  • 是的,这是有道理的。你有没有试过什么?发生了什么?
  • 我猜输出中的is a male child 必须用引号引起来

标签: python list set


【解决方案1】:

作为此类任务的更 Pythonic 方式,您可以使用字典:

>>> li=[['boy','121','is a male child'],['boy','121','is male'],['boy','121','is a child'],['girl','122','is a female child'],['girl','122','is a child']]
>>> 
>>> d={}
>>> 
>>> for i,j,k in li:
...   d.setdefault((i,j),[]).append(k)
... 
>>> d
{('boy', '121'): ['is a male child', 'is male', 'is a child'], ('girl', '122'): ['is a female child', 'is a child']}

setdefault(key[, default])

如果键在字典中,则返回其值。如果不是,则插入值为默认值的键并返回默认值。默认默认为无。

如果您想在 1 个容器中包含元素,您可以遍历项目并将值转换为 tuple,然后使用键对其进行广告:

>>> [i+tuple(j) for i,j in d.items()]
[('boy', '121', 'is a male child', 'is male', 'is a child'), ('girl', '122', 'is a female child', 'is a child')]

正如@jonrsharpe 所说,作为一种更优雅的方式,您也可以使用collections.defaultdict:

>>> from collections import defaultdict
>>> 
>>> d=defaultdict(list)
>>> for i,j,k in li:
...   d[i,j].append(k)
... 
>>> d
defaultdict(<type 'list'>, {('boy', '121'): ['is a male child', 'is male', 'is a child'], ('girl', '122'): ['is a female child', 'is a child']})

【讨论】:

  • @jonrsharpe 简化?当可以使用内置方法完成时,为什么还要使用另一个导入?
  • @jonrsharpe 是的,但在这种情况下,大多数可以使用setdefault 和defaultdict 解决的任务setdefault 具有更高的性能!
  • @jonrsharpe 是的! 这个任务;)
  • 如果您要回答不同的问题,执行不同的任务,其中性能至关重要且差异显着,那么请务必忽略可读性并单独推荐setdefault。不过,您似乎甚至不愿意考虑defaultdict,所以我认为没有必要进一步讨论这个问题。
  • @jonrsharpe 不,实际上我喜欢defaultdict 我的自我,因为它更灵活,而且setdefault 只是它的一部分任务!我同意性能差异不大!无论如何我都会用defaultdict编辑答案,感谢您的关注;)
【解决方案2】:

您可以为此使用itertools.groupby:

>>> l = [['boy','121','is a male child'],['boy','121','is male'],['boy','121','is a child'],['girl','122','is a female child'],['girl','122','is a child']]
>>> import itertools
>>> [k+[m[2] for m in v] for k,v in itertools.groupby(l,key = lambda x:x[:2])]
[['boy', '121', 'is a male child', 'is male', 'is a child'], ['girl', '122', 'is a female child', 'is a child']]

来自文档

itertools.groupby(iterable[, key])

创建一个从可迭代对象中返回连续键和组的迭代器。键是为每个计算键值的函数 元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多