【问题标题】:searching a list for duplicate values in python 2.7在 python 2.7 中搜索重复值的列表
【发布时间】:2017-01-25 21:59:30
【问题描述】:
list1 = ["green","red","yellow","purple","Green","blue","blue"]

所以我得到了一个列表,我想遍历列表并查看颜色是否没有被多次提及。如果有,则不会附加到新列表中。

所以你应该留下

list2 = ["red","yellow","purple"]

所以我试过了

list1 = ["green","red","yellow","purple","Green","blue","blue","yellow"]
list2 =[]
num = 0
for i in list1:
    if (list1[num]).lower == (list1[i]).lower:
        num +=1
    else:
        list2.append(i)
        num +=1

但我不断收到错误

【问题讨论】:

  • @techkris:该链接希望保留每个唯一值的单个副本,而此问题只想保留仅出现一次的值。类似的技术也适用,但在这种情况下会稍微复杂一些。

标签: python python-2.7 list loops


【解决方案1】:

使用Counterhttps://docs.python.org/2/library/collections.html#collections.Counter

from collections import Counter
list1 = ["green","red","yellow","purple","green","blue","blue","yellow"]
list1_counter = Counter([x.lower() for x in list1])
list2 = [x for x in list1 if list1_counter[x.lower()] == 1]

请注意,您的示例是错误的,因为yellow 出现了两次。

【讨论】:

  • 您应该使用.lower(),这似乎是问题的要求。
  • 这不会保留首次出现的顺序。
  • @ShadowRanger:确实,for 循环应该在 list1 上完成。
  • 已编辑,现在应该可以了。
【解决方案2】:

第一个问题是for i in list1: 迭代列表中的元素不是索引,所以有了i,你手中就有了一个元素。

接下来是num,它是一个索引,但您似乎以错误的方式递增它。

我建议您使用以下代码:

for i in range(len(list1)):
    unique = True
    for j in range(len(list1)):
        if i != j and list1[i].lower() == list1[j].lower():
            unique = False
            break
    if unique:
        list2.append(list1[i])

这是如何工作的:这里ij索引,您现在遍历列表,使用i 遍历您可能想要添加的元素的索引,现在您进行测试:您检查列表中的某处是否看到另一个相等的元素。如果是这样,您将unique 设置为False 并为下一个元素执行此操作,否则您添加。

您还可以使用for-else 构造,如@YevhenKuzmovych 说:

for i in range(len(list1)):
    for j in range(len(list1)):
        if i != j and list1[i].lower() == list1[j].lower():
            break
    else:
        list2.append(list1[i])

您可以使用any 使代码更优雅:

for i in range(len(list1)):
    if not any(i != j and list1[i].lower() == list1[j].lower() for j in range(len(list1))):
        list2.append(list1[i])

现在这更优雅但仍然不是很有效。为了提高效率,您可以使用Counter

from collections import Counter

ctr = Counter(x.lower() for x in list1)

一旦你构建了计数器,你就会查找你看到元素的次数,如果它小于 2,你就将它添加到列表中:

from collections import Counter

ctr = Counter(x.lower() for x in list1)

for element in list1:
    if ctr[element.lower()] < 2:
        list2.append(element)

最后你现在甚至可以使用 列表推导 让它变得非常优雅:

from collections import Counter

ctr = Counter(x.lower() for x in list1)

list2 = [element for element in list1 if ctr[element.lower()] < 2]

【讨论】:

  • 您可以删除unique 标志。并将if unique: 更改为else:。只是更蟒蛇的方式。
  • 回溯(最近一次调用最后一次):文件“C:/Python27/testing111.py”,第 6 行,在 如果 i != j 和 list1[i].lower == list [j].lower: TypeError: 'type' object has no attribute 'getitem' >>>
  • @YevhenKuzmovych:但据我所知,else 只有在 for 没有迭代时才会触发。 break 不会触发 else
  • @ylimes: 是的,这是一个错字,忘记了list1 中的1
  • @ylimes:不客气 :) 但只有我有时会厌倦那些只寻找快速复制粘贴的人。 SO 的目的不是做人们的功课等。它旨在解释什么是错误的,为什么是错误的,如何修复它,以及为什么它会这样工作。
【解决方案3】:

这是另一个解决方案:

list2 = []
for i, element in enumerate(list1):
    if element.lower() not in [e.lower() for e in list1[:i] + list1[i + 1:]]:
        list2.append(element)

【讨论】:

  • 不应该是not in吗?
  • 是的,已修复。谢谢。
【解决方案4】:

通过组合内置函数,您可以只保留唯一的项目并且保持外观顺序,只需要一个空类定义和一个单行:

from future_builtins import map  # Only on Python 2 to get generator based map
from collections import Counter, OrderedDict

class OrderedCounter(Counter, OrderedDict):
    pass

list1 = ["green","red","yellow","purple","Green","blue","blue"]

# On Python 2, use .iteritems() to avoid temporary list
list2 = [x for x, cnt in OrderedCounter(map(str.lower, list1)).items() if cnt == 1]

# Result: ['red', 'yellow', 'purple']

您使用Counter 功能来计算可迭代对象,同时从OrderedDict 继承保留键顺序。您所要做的就是过滤结果以检查和去除计数,从而显着降低代码复杂度。

它还将工作减少到原始list 的一次传递,第二次传递的工作与list 中唯一项目的数量成正比,而不必执行原始@987654326 的两次传递@(如果重复很常见并且list 很大,则很重要)。

【讨论】:

    【解决方案5】:

    这是另一个解决方案...

    首先,在我开始之前,我认为这里有一个错字......您将“黄色”列出了两次,并且您指定最后是黄色。因此,为此,我将提供两个脚本,一个允许重复,一个不允许。

    原文:

    list1 = ["green","red","yellow","purple","Green","blue","blue","yellow"]
    list2 =[]
    num = 0
    for i in list1:
        if (list1[num]).lower == (list1[i]).lower:
            num +=1
        else:
            list2.append(i)
            num +=1
    

    已修改(允许重复):

    colorlist_1 = ["green","red","yellow","purple","Green","blue","blue","yellow"]
    colorlist_2 = []
    seek = set()
    
    i = 0
    numberOfColors = len(colorlist_1)
    
    while i < numberOfColors:
        if numberOfColors[i].lower() not in seek:
            seek.add(numberOfColors[i].lower())
            colorlist_2.append(numberOfColors[i].lower())
    
        i+=1
    
    print(colorlist_2)
    
    # prints ["green","red","yellow","purple","blue"]
    

    已修改(不允许重复):

    编辑

    Willem Van Onsem 的回答完全适用并且已经彻底。

    【讨论】:

      猜你喜欢
      • 2019-03-05
      • 2014-12-14
      • 1970-01-01
      • 1970-01-01
      • 2014-06-01
      • 2023-03-31
      • 2017-04-04
      • 2019-05-13
      • 1970-01-01
      相关资源
      最近更新 更多