简体   繁体   English

如何在此列表理解中不获取重复项?

[英]How do I not get duplicates in this list comprehension?

I am trying to take two lists with different lengths, and trying to make a third list which contains the same numbers using list comprehension. 我试图获取两个长度不同的列表,并尝试使用列表推导来制作第三个包含相同数字的列表。 I want to avoid duplicates. 我想避免重复。

I attempted to use list comprehension with an if test, as I will show in the code. 我试图将列表理解与if测试一起使用,如代码所示。 I also attempted an and statement, but that does not work. 我也尝试使用and语句,但这不起作用。

a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
c = [x for x in a if x in b]

This is the current solution I have, 'I also tried to alter the c list comprehension to: 这是我目前拥有的解决方案,“我还尝试将c列表理解更改为:

c = [x for x in a if x in b and x not in c]

But this did not work. 但这没有用。 Is this not possible using list comprehension? 使用列表推导不可能吗? I am aware that I can do this using sets quite easily. 我知道我可以很容易地使用集合来做到这一点。 I am just practicing the use of list comprehension. 我只是在练习使用列表理解。

Depending on your reasons for using a list for c, you could consider using the built-in set structure to do intersection operations and which guarantees uniqueness of elements. 根据对c使用列表的原因,可以考虑使用内置的set结构进行交点操作,这样可以保证元素的唯一性。 For instance, set(a) will produce a set containing the unique elements in a . 例如, set(a)将产生含有独特的元件的一组a

c = [x for x in a if x in b] does not work since the duplicate elements in a are still contained in b and therefore not excluded by your if statement. c = [x for x in a if x in b]不起作用,因为在重复元素a都仍包含在b ,因此不会被你的if语句排除。 ( 1 is duplicated in a , but both elements will be contained in c by your first definition, since 1 is in b ). 1a中重复,但是两个元素都将由您的第一个定义包含在c ,因为1b )。

EDIT: if you want to simply modify your list comprehension but continue using it, you could do something like: c = [x for x in set(a) if x in b] 编辑:如果您只想修改列表理解但继续使用它,则可以执行以下操作: c = [x for x in set(a) if x in b]

If you want a new list of all elements that appear in either of the 2 original lists, you could use the set class to achieve that. 如果您想要一个包含在两个原始列表中的任何一个中的所有元素的新列表,则可以使用set类来实现。 Maybe like this: 也许是这样的:

>>> a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

>>> list(sorted(set(a) | set(b)))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 21, 34, 55, 89]

What this does is building 2 sets from the lists, then finding the union of all the elements and then convert the result back to a list. 这样做是从列表建设2台,然后找到该工会的所有元素,然后将结果转换回列表。

This approach will be faster than checking elem for elem in a if elem in b for large lists, because membership tests are O(1) for sets but up to O(n) for lists. 这种方法比检查大型列表elem for elem in a if elem in b更快,因为对于集合而言,成员资格测试为O(1) ,但对于列表而言,最高为O(n)

I will present a slightly different solution: The idea would be to first count the frequency of numbers using Counter and then perform the list comprehension using the keys. 我将提出一个略有不同的解决方案:这个想法是首先使用Counter计数数字的频率,然后使用键执行列表理解。 Since Counter returns a dictionary, you will not have duplicate keys. 由于Counter返回字典,因此不会有重复的键。

from collections import Counter

a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

f1 = Counter(a)
f2 = Counter(b)

c = [x for x in f1.keys() if x in f2.keys()]
# [1, 2, 3, 5, 8, 13]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM