问题 根据任意标准嵌套平面列表


我有一个独特的对象列表,其中一些可能与其他对象共享一个给定的属性。我希望创建一个嵌套的列表列表,其中对象按给定属性分组。作为一个最小的例子,给出以下列表:

>>> flat = ["Shoes", "pants", "shirt", "tie", "jacket", "hat"]

我可能想按长度分组,例如:

>>> nest_by_length(flat)
[['tie', 'hat'], ['shoes', 'pants', 'shirt'], ['jacket']]

我见过几个 类似  问题 和 建议。但是,在所有这些情况下,嵌套都基于输入列表的顺序。在我的例子中,输入列表的排序是完全不可预测的,输出的子列表的数量和每个子列表的项目数量也是如此。

是否有标准功能或惯用方法来实现这一目标?


4685
2018-05-12 17:59


起源



答案:


现有列表的常用习惯用法是使用 通过...分组 在itertools中:

from itertools import groupby

flat = ["Shoes", "pants", "shirt", "tie", "jacket", "hat"]

result=[]
for k, g in groupby(sorted(flat, key=len), key=len):
    result.append(list(g))

print result   

或者,更简洁:

[list(g) for _,g in groupby(sorted(flat, key=len), key=len)]

打印:

[['tie', 'hat'], ['Shoes', 'pants', 'shirt'], ['jacket']]

输入到 groupby 在这种情况下,基于键函数的输出的变化值将组分组 len。通常,您需要根据相同的键功能预先排序列表,所以 sorted 首先调用函数。

如果您的源列表尚未完成,或者根据条件无法排序(或者您只是喜欢其他选项),请创建一个将您的条件映射到唯一键值的dict:

groups={}
for e in flat:
    groups.setdefault(len(e), []).append(e)

print groups    
# {5: ['Shoes', 'pants', 'shirt'], 3: ['tie', 'hat'], 6: ['jacket']}

你也可以使用 defaultdict 而不是使用任意键值setdefault:

from collections import defaultdict
groups=defaultdict(list)
for e in flat:
    groups[len(e)].append(e)  
# groups=defaultdict(<type 'list'>, {5: ['Shoes', 'pants', 'shirt'], 3: ['tie', 'hat'], 6: ['jacket']})

在任何一种情况下,您都可以从中创建嵌套列表:

>>> [groups[k] for k in sorted(groups.keys())] 
[['tie', 'hat'], ['Shoes', 'pants', 'shirt'], ['jacket']]

10
2018-05-12 18:03



我很感激你的彻底性。我怀疑会有类似groupby的功能,我不知道,但字典技巧只是聪明。谢谢! - Joe


答案:


现有列表的常用习惯用法是使用 通过...分组 在itertools中:

from itertools import groupby

flat = ["Shoes", "pants", "shirt", "tie", "jacket", "hat"]

result=[]
for k, g in groupby(sorted(flat, key=len), key=len):
    result.append(list(g))

print result   

或者,更简洁:

[list(g) for _,g in groupby(sorted(flat, key=len), key=len)]

打印:

[['tie', 'hat'], ['Shoes', 'pants', 'shirt'], ['jacket']]

输入到 groupby 在这种情况下,基于键函数的输出的变化值将组分组 len。通常,您需要根据相同的键功能预先排序列表,所以 sorted 首先调用函数。

如果您的源列表尚未完成,或者根据条件无法排序(或者您只是喜欢其他选项),请创建一个将您的条件映射到唯一键值的dict:

groups={}
for e in flat:
    groups.setdefault(len(e), []).append(e)

print groups    
# {5: ['Shoes', 'pants', 'shirt'], 3: ['tie', 'hat'], 6: ['jacket']}

你也可以使用 defaultdict 而不是使用任意键值setdefault:

from collections import defaultdict
groups=defaultdict(list)
for e in flat:
    groups[len(e)].append(e)  
# groups=defaultdict(<type 'list'>, {5: ['Shoes', 'pants', 'shirt'], 3: ['tie', 'hat'], 6: ['jacket']})

在任何一种情况下,您都可以从中创建嵌套列表:

>>> [groups[k] for k in sorted(groups.keys())] 
[['tie', 'hat'], ['Shoes', 'pants', 'shirt'], ['jacket']]

10
2018-05-12 18:03



我很感激你的彻底性。我怀疑会有类似groupby的功能,我不知道,但字典技巧只是聪明。谢谢! - Joe