我正在寻找以下问题的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编程的新领域。答案 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:])等等。重要的是避免每次从开始检查。
我无法测试这个例子,但我认为它应该可行:)。
希望得到这个帮助。