如何找到重复的元素并将其删除?

时间:2017-09-29 10:21:22

标签: python python-2.7 numpy

我有两个列表如下:

cls

这意味着A属于1级,其得分为0.1,B属于2级,得分为0.2,依此类推。

我正在寻找一种方法来查找具有相同类的对象,如果该对象的分数小于该类中的另一个对象(name =[C , D , E , F ] cls =[3 , 2 , 4 , 1 ] score=[0.5 ,0.3 , 1 , 0.8 ] ),则删除该对象。所以,我的预期结果是

name

clsscorename_clean=[] cls_clean=[] score_clean=[] for i in range(len(cls)-1): cls_i=cls[i] max_index = -1 for j in range(i+1,len(cls)): cls_j = cls[j] if (cls_i==cls_j): if (score[i]<=score[j]): max_index=j else: max_index=i if (max_index>=0): name_clean.append(name[max_index]) cls_clean.append(cls[max_index]) score_clean.append(score[max_index]) else: name_clean.append(name[i]) cls_clean.append(cls[i]) score_clean.append(score[i]) 是列表类型。我怎么能在python中实现它?感谢

这就是我做的事情

O(log n)

4 个答案:

答案 0 :(得分:2)

请注意,您不能将class用作变量名,因为它是Python中的保留关键字。

我会考虑使用一个包含namedtuple或一个表的列表,而不是使用3个列表,例如pandas.DataFrame

但是,由于你有3个列表,我会这样做:

获得每个班级的最高分并将其存储在字典中

highest_scores = {}
for c, s in zip(cls, score):
    current_max = highest_scores.get(c, None)
    if current_max is None or current_max < s:  # not present or smaller
        highest_scores[c] = s

然后再次遍历列表,只保留那些分数等于该类存储分数的分数:

new_name = []
new_cls = []
new_score = []
for n, c, s in zip(name, cls, score):
    if s == highest_scores[c]:
        new_name.append(n)
        new_cls.append(c)
        new_score.append(s)

给出了:

>>> new_name
['C', 'D', 'E', 'F']
>>> new_cls
[3, 2, 4, 1]
>>> new_score
[0.5, 0.3, 1, 0.8]

请注意,这将保持每个班级的所有“最高分”,因此如果您拥有相同的班级和相同的分数,这将保持两者。要解决此问题,您可以在找到第一个密钥后立即从字典中删除密钥。

for n, c, s in zip(name, cls, score):
    if c in highest_scores and s == highest_scores[c]:
        new_name.append(n)
        new_cls.append(c)
        new_score.append(s)
        del highest_scores[c]

答案 1 :(得分:1)

使用正确的数据结构有很大帮助。在您的情况下,您希望按class重新整理数据:

names = ["A",  "B", "C", "D", "E",  "F"]
classes = [1,  2  ,  3  , 2   , 4 ,  1]
scores = [0.1, 0.2 , 0.5 , 0.3 , 1 , 0.8]

byclasses = defaultdict(list)
for name, class_, score in zip(names, classes, scores):
    byclasses[class_].append((score, name))

print byclasses

在这个阶段你得到的是:

{1: [(0.1, 'A'), (0.8, 'F')], 
 2: [(0.2, 'B'), (0.3, 'D')], 
 3: [(0.5, 'C')], 
 4: [(1, 'E')]
}

现在你只需要对每个列表进行排序(它们将按照得分升序排序)并保留每个列表的最后一项(这将是得分最高的一个)

cleaned = [((k,) + sorted(v)[-1]) for k, v in byclasses.items()]
print cleaned

它为您提供了(类,分数,名称)元组的列表:

[(1, 0.8, 'F'), (2, 0.3, 'D'), (3, 0.5, 'C'), (4, 1, 'E')]

和 - 如果你坚持使用三个列表而不是一个元组列表 - 将结果解压缩到三个新列表:

cnames, cclasses, cscores = (list(c) for c in zip(*cleaned))
print cnames, cclasses, cscores

我们在这里:

[1, 2, 3, 4] [0.8, 0.3, 0.5, 1] ['F', 'D', 'C', 'E']

答案 2 :(得分:1)

以下解决方案将问题分为两个不同的步骤,

  1. 查找每个项目类别的最高分数并将其存储为地图
  2. 创建仅包含与最高得分相对应的项目的新列表
  3. 注意使用set()查找不同的类

    name = ['A', 'B', 'C', 'D', 'E', 'F']
    cls = [1, 2, 3, 2, 4, 1]
    score = [0.1, 0.2, 0.5, 0.3, 1, 0.8]
    
    # find largest score for each class
    max_class_scores = {} # key is class, value is max score
    for c in set(cls):
        # contains max score for a class
        max_class_scores[c] = max(s for (i,s) in enumerate(score) if cls[i]==c)
    
    new_name = []
    new_cls = []
    new_score =[]
    for n,c,s in zip(name,cls,score):
        max_score = max_class_scores[c]
        if s == max_score :  # only process where the current record is max for the class
            new_name.append(n)
            new_cls.append(c)
            new_score.append(s)
    
    print(new_name,new_cls,new_score)
    

答案 3 :(得分:1)

   x =: i. 2 3
0 1 2 
3 4 5
   y =: i. 3 2
0 1
2 3
4 5