我有两个列表如下:
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
cls
,score
和name_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)
答案 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)
以下解决方案将问题分为两个不同的步骤,
注意使用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