处理列表列表,查找所有具有匹配最后值的列表?
Process a list of lists, finding all lists that have matching last values?
给定一个列表列表
lol = [[0,a], [0,b],
[1,b], [1,c],
[2,d], [2,e],
[2,g], [2,b],
[3,e], [3,f]]
我想提取所有具有相同最后一个元素 (lol[n][1]
) 的子列表,并得到如下所示的内容:
[0,b]
[1.b]
[2,b]
[2,e]
[3,e]
我知道给定两个列表我们可以使用交集,除了在 for each 循环中递增索引值之外,解决此类问题的正确方法是什么?
1。使用 collections.defaultdict
您可以使用 defaultdict
首先将多次出现的项目分组,然后迭代 dict.items
以获得您需要的内容。
from collections import defaultdict
lol = [[0,'a'], [0,'b'],
[1,'b'], [1,'c'],
[2,'d'], [2,'e'],
[2,'g'], [2,'b'],
[3,'e'], [3,'f']]
d = defaultdict(list)
for v,k in lol:
d[k].append(v)
# d looks like -
# defaultdict(list,
# {'a': [0],
# 'b': [0, 1, 2],
# 'c': [1],
# 'd': [2],
# 'e': [2, 3],
# 'g': [2],
# 'f': [3]})
result = [[v,k] for k,vs in d.items() for v in vs if len(vs)>1]
print(result)
[[0, 'b'], [1, 'b'], [2, 'b'], [2, 'e'], [3, 'e']]
2。使用 pandas.duplicated
以下是如何使用 Pandas -
执行此操作
- 转换为 pandas 数据帧
- 对于关键列,找到重复项并全部保留
- 在忽略索引的同时转换为记录列表
import pandas as pd
df = pd.DataFrame(lol, columns=['val','key'])
dups = df[df['key'].duplicated(keep=False)]
result = list(dups.to_records(index=False))
print(result)
[(0, 'b'), (1, 'b'), (2, 'e'), (2, 'b'), (3, 'e')]
3。使用 numpy.unique
您可以使用 numpy 以矢量化方式解决此问题 -
- 转换为 numpy 矩阵
arr
- 查找唯一元素
u
及其计数 c
- 过滤出现不止一次的唯一元素列表
dup
- 使用广播比较数组的第二列,并取任何超过 axis=0 的值得到一个布尔值,对于重复的行为 True
- 根据这个布尔值
过滤arr
import numpy as np
arr = np.array(lol)
u, c = np.unique(arr[:,1], return_counts=True)
dup = u[c > 1]
result = arr[(arr[:,1]==dup[:,None]).any(0)]
result
array([['0', 'b'],
['1', 'b'],
['2', 'e'],
['2', 'b'],
['3', 'e']], dtype='<U21')
给定一个列表列表
lol = [[0,a], [0,b],
[1,b], [1,c],
[2,d], [2,e],
[2,g], [2,b],
[3,e], [3,f]]
我想提取所有具有相同最后一个元素 (lol[n][1]
) 的子列表,并得到如下所示的内容:
[0,b]
[1.b]
[2,b]
[2,e]
[3,e]
我知道给定两个列表我们可以使用交集,除了在 for each 循环中递增索引值之外,解决此类问题的正确方法是什么?
1。使用 collections.defaultdict
您可以使用 defaultdict
首先将多次出现的项目分组,然后迭代 dict.items
以获得您需要的内容。
from collections import defaultdict
lol = [[0,'a'], [0,'b'],
[1,'b'], [1,'c'],
[2,'d'], [2,'e'],
[2,'g'], [2,'b'],
[3,'e'], [3,'f']]
d = defaultdict(list)
for v,k in lol:
d[k].append(v)
# d looks like -
# defaultdict(list,
# {'a': [0],
# 'b': [0, 1, 2],
# 'c': [1],
# 'd': [2],
# 'e': [2, 3],
# 'g': [2],
# 'f': [3]})
result = [[v,k] for k,vs in d.items() for v in vs if len(vs)>1]
print(result)
[[0, 'b'], [1, 'b'], [2, 'b'], [2, 'e'], [3, 'e']]
2。使用 pandas.duplicated
以下是如何使用 Pandas -
执行此操作- 转换为 pandas 数据帧
- 对于关键列,找到重复项并全部保留
- 在忽略索引的同时转换为记录列表
import pandas as pd
df = pd.DataFrame(lol, columns=['val','key'])
dups = df[df['key'].duplicated(keep=False)]
result = list(dups.to_records(index=False))
print(result)
[(0, 'b'), (1, 'b'), (2, 'e'), (2, 'b'), (3, 'e')]
3。使用 numpy.unique
您可以使用 numpy 以矢量化方式解决此问题 -
- 转换为 numpy 矩阵
arr
- 查找唯一元素
u
及其计数c
- 过滤出现不止一次的唯一元素列表
dup
- 使用广播比较数组的第二列,并取任何超过 axis=0 的值得到一个布尔值,对于重复的行为 True
- 根据这个布尔值 过滤
arr
import numpy as np
arr = np.array(lol)
u, c = np.unique(arr[:,1], return_counts=True)
dup = u[c > 1]
result = arr[(arr[:,1]==dup[:,None]).any(0)]
result
array([['0', 'b'],
['1', 'b'],
['2', 'e'],
['2', 'b'],
['3', 'e']], dtype='<U21')