在列表列表中查找重复元素

时间:2015-05-26 23:42:57

标签: python duplicates nested-lists

我正在寻找以下问题的Python想法。

给出列表清单......

[[20, 21, 22], [17, 18, 19, 20], [10, 11, 12, 13]]

如果任何或所有列表之间存在重复的重复元素,则返回True。如果所有元素都是唯一的,则返回False。

在上面的示例中,20是常见的并且将返回True。下面的示例将返回False,因为列表之间的所有数字都是唯一的。

[[20, 21, 22], [17, 18, 19], [10, 11, 12, 13]]

最后,不需要在单个列表中测试重复项,因为数字始终是连续的。

仅供参考 - 此问题将用于优化航空公司机组人员的月度时间表。每个列表代表3天,4天或5天的航班旅行,不能重叠。

顺便说一句 - 这个问题不是一个任务,而是个人追求减少工作并获得更多报酬:)对不起它不清楚。我尝试了一种有效的蛮力方法,但希望有更优雅的Pythonic方法。我感谢所有的回复,因为他们引领我进入Python编程的新领域。

8 个答案:

答案 0 :(得分:3)

num = Counter(i for j in alist for i in j) # flatten list into a single dimension
dup = [k for k, v in num.items() if v > 1] # checks the dict for duplicate values

答案 1 :(得分:2)

如果您愿意放弃列表理解的优雅,您可以执行以下操作:

seen, dups = set(), set()
for l in ll:
    dups = dups.union(seen.intersection(set(l)))
    seen = seen.union(set(l))

您的答案应该在dups

修改

Steven Rumbalski所述set set - 成员操作'}争论是多余的(并且不必要地昂贵)。

答案 2 :(得分:1)

假设您正在寻找特定的目标(您的问题不明确):

def find_dupe(lists, target):
    seen = set()
    for lst in lists:
        for item in lst:
            if item == target and item in seen:
                return True
            seen.add(item)

样本:

>>> find_dupe([[20, 21, 22], [17, 18, 19, 20], [10, 11, 12, 13]],
              20)
True

如果不是,那么您可以简单地删除item == target条件

def find_dupe(lists):
    seen = set()
    for lst in lists:
        for item in lst:
            if item in seen:
                yield item
            seen.add(item)

答案 3 :(得分:0)

>>> from collections import Counter
>>> list_of_list = [[20, 21, 22], [17, 18, 19, 20], [10, 11, 12, 13]]
>>> counts = Counter(item for sublist in list_of_list for item in sublist)
>>> repeated_items = [item for item, count in counts.items() if count > 1]
>>> repeated_items
[20]

答案 4 :(得分:0)

这样的事情:

l = [[20, 21, 22], [17, 18, 19, 20], [10, 11, 12, 13]]
dupes = []
flat = [item for sublist in l for item in sublist]
for f in flat:
    if flat.count(f) > 1:
        if f not in dupes:
            dupes.append(f)

if dupes:
    return True
else:
    return False

答案 5 :(得分:0)

旨在提高效率。

def duplicates_exist(ll):
    seen = set()
    see = seen.add
    for l in ll:
        for element in set(l):
            if element in seen:
                return True
            see(element)
    return False

@Stefan Pochmann's answer让我意识到我之前有一台不必要的发电机。 > _<

答案 6 :(得分:0)

>>> seen = set()
>>> any(element in seen or seen.add(element)
        for lst in lists for element in set(lst))
True

我只使用set(lst)而不是lst,因为不清楚子列表是否可以包含重复项。

正如@Shashank所暗示的那样,这是有效的,因为它在第一个找到的副本处停止(就像Shashank's solution)。如果有很多子列表,但前两个中有重复,那么其余的子列表甚至都不会被查看。因此,它比首先收集来自所有地方的所有重复项的解决方案更快,然后仅在之后将其转换为布尔值。

更新: @ abarnert的评论让我想起了这个:

>>> max(Counter(chain.from_iterable(ll)).values()) > 1
True

或更短(但更慢):

>>> max(Counter(sum(lists, [])).values()) > 1
True

这两个不处理单个子列表中的重复项,但我发现假设不会发生这种情况是合理的,否则规范应该这样说,或者至少该示例应该有一个。

答案 7 :(得分:-1)

我建议你试试这个:

def find_dup(listOfLists):
   for index in range(len(listOfLists) - 1)
      result = [filter(lambda x: x in listOfLists[index], otherLists) for otherLists in listOfLists[index+1:]]
      if result:
          return True
   return False

想法是查看第一个列表(listOfLists [0])并检查其中任何元素是否在其他列表中重复(listOfLists [1:]),在肯定的情况下返回True,在否定的情况下,看看第二个列表(listOfLists [1])并再看一下其他列表(listOfLists [2:])等等。重要的是避免每次从开始检查。

我无法测试这个例子,但我认为它应该可行:)。

希望得到这个帮助。