【问题标题】:Process a list of lists, finding all lists that have matching last values?处理列表列表,查找所有匹配最后一个值的列表?
【发布时间】:2021-11-24 00:53:37
【问题描述】:

给定一个列表列表

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]

我知道给定两个列表我们可以使用交集,除了在每个循环中增加索引值之外,解决此类问题的正确方法是什么?

【问题讨论】:

  • 遍历列表中的每个子列表:提取子列表的最后一个元素(在您的示例中为'a, b`),并将其附加到列表字典中提取的元素。例如{'a': [[0, 'a']], 'b': [[0, 'b'],[1, 'b']]}.
  • 我添加了多种方法,您可以以 Python 方式执行此操作。一定要检查一下。

标签: python set intersection


【解决方案1】:

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 做到这一点 -

  1. 转换为 pandas 数据帧
  2. 对于键列,找到重复项并保留所有项
  3. 在忽略索引的情况下转换为记录列表
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 以矢量化方式解决此问题 -

  1. 转换为numpy矩阵arr
  2. 查找独特元素u 及其计数c
  3. 过滤多次出现的唯一元素列表dup
  4. 使用广播比较数组的第二列,并取任何 overaxis=0 来获得一个布尔值,对于重复的行为 True
  5. 根据这个布尔值过滤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')

【讨论】:

  • 你介意解释一下这行吗,你把这种线性嵌套叫做什么?如果以更传统的方式编写为嵌套循环,我假设 d.item 中的 k,vs 将是最外层的 for 循环?结果 = [[v,k] for k,vs in d.items() for v in vs if len(vs)>1
  • 当然,检查nested loops in list comprehension。一般结构是[item for sublist in list for item in sublist]而不是[item for item in sublist for sublist in list]
  • 所以我正在迭代分组字典中的项目,并且对于字典值中的每个元素(vs 这是一个列表),我再次迭代子列表以获得@987654338 @,条件是 len(vs)&gt;1 重复。然后我只是将它与相应的k 耦合并将其作为列表列表返回。
  • 希望能澄清你的问题。让我知道是否有任何混淆。此外,如果它有助于解决您的查询,请随时标记答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多