根据元组的第二项从元组列表中删除列表项

时间:2018-09-27 06:30:34

标签: python python-3.x tuples

我有一个元组列表:

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

里面有什么问题?

4 个答案:

答案 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))]