我有一个元组列表:
ap = [('unknown', (81, 717, 236, 562)), ('unknown', (558, 1033, 825, 765)), ('unknown', (96, 1142, 225, 1013)), ('Jenny', (558, 1033, 825, 765)), ('unknown', (477, 1233, 632, 1078)), ('unknown', (741, 1199, 868, 1070)), ('Garry', (53, 282, 182, 153)), ('Sam', (477, 1233, 632, 1078)), ('Chen', (593, 283, 779, 97)), ('Steve', (741, 1199, 868, 1070)), ('unknown', (53, 282, 182, 153)), ('Harry', (81, 717, 236, 562)), ('unknown', (593, 283, 779, 97))]
如果元组的第二个项目与任何其他元组相同,我想对它进行排序,则将具有第一项的元组保留为“未知”,并删除具有第一项的元组为“未知”。输出应为:
ap = [('Harry',(81, 717, 236, 562)), ('Jenny', (558, 1033, 825, 765)), ('unknown', (96, 1142, 225, 1013)), ('Sam', (477, 1233, 632, 1078)), ('Steve', (741, 1199, 868, 1070)), ('Garry', (53, 282, 182, 153)), ('Chen', (593, 283, 779, 97))]
我尝试了以下代码:
for i in ap:
for j in ap:
if i[1] == j[1]:
if i[0] == "unknown":
del i
else:
del j
但是它给出了这个错误:
Traceback (most recent call last):
File "<stdin>", line 3, in <module>
NameError: name 'i' is not defined
里面有什么问题?
答案 0 :(得分:2)
del语句
删除名称会从本地或本地删除该名称的绑定 全局名称空间,取决于名称是否出现在全局名称空间中 同一代码块中的语句。如果名称未绑定,则为NameError 将会引发异常。
为此任务最好使用dictionary
。
expected = [('Harry',(81, 717, 236, 562)), ('Jenny', (558, 1033, 825, 765)),
('unknown', (96, 1142, 225, 1013)), ('Sam', (477, 1233, 632, 1078)),
('Steve', (741, 1199, 868, 1070)), ('Garry', (53, 282, 182, 153)), ('Chen', (593, 283, 779, 97))]
person_dict = {}
for person_name, person_val in ap:
if person_val not in person_dict:
# create key using tuple item 2
person_dict[ person_val] = person_name
# key already exist so we only want to update its value if it is still unknown
elif person_dict[ person_val] == 'unknown':
person_dict[ person_val] = person_name
ap = [(v,k) for k, v in person_dict.items()]
print(ap == expected) # True
答案 1 :(得分:2)
这里简短而简单的答案:列表理解
ap = [ ('unknown', (81, 717, 236, 562)),
('unknown', (558, 1033, 825, 765)),
('unknown', (96, 1142, 225, 1013)),
('Jenny', (558, 1033, 825, 765)),
('unknown', (477, 1233, 632, 1078)),
('unknown', (741, 1199, 868, 1070)),
('Garry', (53, 282, 182, 153)),
('Sam', (477, 1233, 632, 1078)),
('Chen', (593, 283, 779, 97)),
('Steve', (741, 1199, 868, 1070)),
('unknown', (53, 282, 182, 153)),
('Harry', (81, 717, 236, 562)),
('unknown', (593, 283, 779, 97))]
known = [my_tuple[1] for my_tuple in ap if my_tuple[0] != "unknown"]
output = [my_tuple for my_tuple in ap if (my_tuple[1] in known and my_tuple[0] != "unknown") or my_tuple[1] not in known]
print(output)
然后输出是:
[('unknown', (96, 1142, 225, 1013)), ('Jenny', (558, 1033, 825, 765)), ('Garry', (53, 282, 182, 153)), ('Sam', (477, 1233, 632, 1078)), ('Chen', (593, 283, 779, 97)), ('Steve', (741, 1199, 868, 1070)), ('Harry', (81, 717, 236, 562))]
这里发生的是,我们正在将所有第二个元组元素收集到一个名称不是“未知”(使用列表理解)的列表中。
然后,我们再次使用列表推导,首先添加所有已知第二个元素且名称不是“ unknown”的元组,然后再添加任何真正的未知数。
这听起来可能令人困惑,希望您理解我的意思。如果您有任何问题,请告诉我。
答案 2 :(得分:0)
在两个循环中使用相同的集合,并在循环内部从集合中删除在这里造成了问题。我认为最好创建一个应删除的新项目列表,并在此循环后将其删除。
toDelete = []
for i in ap:
for j in ap:
if i[1] == j[1] and not ap.index(i) == ap.index(j):
if i[0] == "unknown":
toDelete.append(i)
else:
toDelete.append(j)
for i in toDelete:
try:
ap.remove(i)
except Exception as e:
pass
try-catch在那里,因为每个要更新的元素在toDelete中出现两次。
可以通过将第二个循环设为:
来避免这种情况。for j in ap[ap.index(i)+1:]:
答案 3 :(得分:0)
另一种方法可能是使用collections
在原始列表中创建重复列表,然后通过检查哪个元素重复来创建新的元组列表。然后,创建一个新列表,检查哪个元素不是重复的,或者哪个元素不是unknown
:
import collections
# Create a list of elements that are duplicate in the original list
duplicates = [item for item, count in collections.Counter([x[1] for x in ap]).items() if count > 1]
new = []
for elem in ap:
if elem[1] in duplicates:
if elem[0] != 'unknown':
# Copy the duplicate element only if it's not unknown
new.append(elem)
else:
new.append(elem)
print 'New list: ',new
输出为:
new list: [('unknown', (96, 1142, 225, 1013)), ('Jenny', (558, 1033, 825, 765)), ('Garry', (53, 282, 182, 153)), ('Sam', (477, 1233, 632, 1078)), ('Chen', (593, 283, 779, 97)), ('Steve', (741, 1199, 868, 1070)), ('Harry', (81, 717, 236, 562))]