【问题标题】:Keep only sublist in list if the 2nd elements are repeating如果第二个元素重复,则仅在列表中保留子列表
【发布时间】:2016-12-14 12:17:11
【问题描述】:

示例

list = [['1', '13/12/2016', [42, 52]], ['2', '12/12/2016', [36, 46]], ['4', '10/12/2016', [13, 23]], ['4', '10/12/2016', [42, 52]], ['5', '08/12/2016', [42, 52]], ['6', '07/12/2016', [32, 42]], ['7', '12/12/2016', [42, 52]], ['8', '06/12/2016', [42, 52]], ['10', '12/12/2016', [45, 55]], ['11', '08/12/2016', [42, 52]]]

我想检查每个子列表的所有第二个元素是否重复。
如果第二个元素在另一个子列表中重复,我想保留整个子列表

预期结果

endlist = [['2', '12/12/2016', [36, 46]], ['4', '10/12/2016', [13, 23]], ['4', '10/12/2016', [42, 52]], ['5', '08/12/2016', [42, 52]], ['7', '12/12/2016', [42, 52]], ['10', '12/12/2016', [45, 55]], ['11', '08/12/2016', [42, 52]]]

(08/12/2016 | 10/12/2016 | 12/12/2016 是双打)

我知道如何使用平面列表 ([x for x in l if l.count(x) > 1]) 保留双打,但是如何在带有子列表的列表中做到这一点?

【问题讨论】:

  • 你为什么扔掉第一个元素? ['1', '13/12/2016', [42, 52]] 的第二个位置有一个 len = 2 列表
  • 为什么不直接做 '([x[1] for x in l if l.count(x[1]) > 1])' ?
  • @GáborErdős,我不明白你的问题

标签: python list python-3.x


【解决方案1】:

您可以使用列表推导:

lst = [['1', '13/12/2016', [42, 52]], ['2', '12/12/2016', [36, 46]], ['4', '10/12/2016', [13, 23]], ['4', '10/12/2016', [42, 52]], ['5', '08/12/2016', [42, 52]], ['6', '07/12/2016', [32, 42]], ['7', '12/12/2016', [42, 52]], ['8', '06/12/2016', [42, 52]], ['10', '12/12/2016', [45, 55]], ['11', '08/12/2016', [42, 52]]]
endlist = [sublist for sublist in lst if sum(x[1] == sublist[1] for x in lst) > 1]
# [['2', '12/12/2016', [36, 46]], ['4', '10/12/2016', [13, 23]], ['4', '10/12/2016', [42, 52]], ['5', '08/12/2016', [42, 52]], ['7', '12/12/2016', [42, 52]], ['10', '12/12/2016', [45, 55]], ['11', '08/12/2016', [42, 52]]]

【讨论】:

  • 朱利安,你能帮我做一件事吗?如果我只想插入找到的第一个双字符串,我必须在您的答案中进行哪些更改?
【解决方案2】:

您可以将计数信息收集到字典中,然后使用它。如果列表很大,这将很好地扩展:

myList = [['1', '13/12/2016', [42, 52]], ['2', '12/12/2016', [36, 46]], ['4', '10/12/2016', [13, 23]], ['4', '10/12/2016', [42, 52]], ['5', '08/12/2016', [42, 52]], ['6', '07/12/2016', [32, 42]], ['7', '12/12/2016', [42, 52]], ['8', '06/12/2016', [42, 52]], ['10', '12/12/2016', [45, 55]], ['11', '08/12/2016', [42, 52]]]

d = dict()
for subList in myList:
    if subList[1] in d:
        d[subList[1]] += 1
    else:
        d[subList[1]] = 1

doubles = [subList for subList in myList if d[subList[1]] >= 2]

如果您希望doubles 排除三元组等,当然可以将>=2 替换为==2

编辑时:如果您想保留每个双倍子列表的第一次出现,请修改字典以便它存储每个元素的索引。像这样的:

d = dict()
for i,subList in enumerate(myList):
    if subList[1] in d:
        d[subList[1]].append(i)
    else:
        d[subList[1]] = [i]

firsts = [subList for i,subList in enumerate(myList) if len(d[subList[1]]) >= 2 and i == d[subList[1]][0]]
print(firsts) #prints [['2', '12/12/2016', [36, 46]], ['4', '10/12/2016', [13, 23]], ['5', '08/12/2016', [42, 52]]]

进一步编辑:这是一个删除后续双打的解决方案:

d = dict()

for i,subList in enumerate(myList):
    if not subList[1] in d:
        d[subList[1]] = i #stores first index

noDoubles = [subList for i,subList in enumerate(myList) if i == d[subList[1]]]

【讨论】:

  • 谢谢你,约翰,我给了 Julien “接受答案”,因为他是第一个解决我的问题的人,但我非常喜欢这样一个事实,即我可以像你的答案一样过滤双打。
  • @Reman 接受最能满足您需求的任何答案。我认为这是一个规模问题。在一定规模以下,单行列表理解的优雅(如在另一个答案中)胜出。超过一定比例时,其中的两个 for 使其成为二次方这一事实变得很重要,在这种情况下,您需要在 1 遍中收集计数,然后再在第二遍中构造结束列表。
  • 你能帮我做一件事吗?如果我只想插入找到的第一个双字符串,我必须在您的答案中进行哪些更改?
  • @Reman 这会起作用,但是我在编辑后的答案中构造字典的方式具有所有索引列表都是非空的属性,因此测试len(d[subList[1]]) >= 1 是多余的。在这种情况下,存储超过 1 个索引是没有意义的。我将为这种情况添加第三种解决方案。
  • @Reman -- 是的,就是这个想法。如果您覆盖以前的索引,则仅保留最后一个。在这个阶段,Stack Overflow 的评论软件开始给出礼貌的警告。关于避免长时间讨论 -- 如果您还有其他问题,请将它们作为新问题发布。
猜你喜欢
  • 1970-01-01
  • 2020-12-24
  • 1970-01-01
  • 1970-01-01
  • 2022-12-07
  • 1970-01-01
  • 1970-01-01
  • 2016-03-21
  • 2021-11-27
相关资源
最近更新 更多