我有一个元组列表,每个元组有两个项目;第一项是字典,第二项是字符串。
all_values = [
({'x1': 1, 'y1': 2}, 'str1'),
({'x2': 1, 'y2': 2}, 'str2'),
({'x3': 1, 'y3': 2}, 'str3'),
({'x4': 1, 'y4': 2}, 'str1'),
]
我想根据元组的第二项从列表中删除重复数据。我写了这段代码,但我想改进它:
flag = False
items = []
for index, item in enumerate(all_values):
for j in range(0, index):
if all_values[j][1] == all_values[index][1]:
flag = True
if not flag:
items.append(item)
flag = False
得到这个:
items = [
({'x1': 1, 'y1': 2}, 'str1'),
({'x2': 1, 'y2': 2}, 'str2'),
({'x3': 1, 'y3': 2}, 'str3')
]
任何帮助?
BTW我尝试使用list(set(all_values))
删除重复数据,但收到错误unhashable type: dict
。
答案 0 :(得分:1)
使用另一个列表(' strings')来收集元组的第二个字符串项。因此,您可以清楚地检查当前列表项是否重复。
在下面的代码中,我添加了一个重复的列表项(带有' str2'值)用于演示目的。
all_values = [
({'x1': 1, 'y1': 2}, 'str1'),
({'x2': 1, 'y2': 2}, 'str2'),
({'x5': 8, 'ab': 7}, 'str2'),
({'x3': 1, 'y3': 2}, 'str3')
]
strings = []
result = []
for value in all_values:
if not value[1] in strings:
strings.append(value[1])
result.append(value)
新的非重复列表将在'结果'。
答案 1 :(得分:0)
您可以使用以下代码
items = []
for item in all_values:
if next((i for i in items if i[1] == item[1]), None) is None:
items.append(item)
答案 2 :(得分:0)
items = []
[items.append(item) for item in all_values if item[1] not in [x[1] for x in items]]
print items
答案 3 :(得分:0)
面向对象的方法并不短 - 但它更直观,可读/可维护(恕我直言)。
首先创建一个模仿元组的对象,然后提供额外的hash()
和eq()
函数,稍后Set
将使用这些函数来检查对象的唯一性。
声明函数__repr__()
用于调试目的:
class tup(object):
def __init__(self, t):
self.t = t
def __eq__(self, other):
return self.t[1] == other.t[1]
def __hash__(self):
return hash(self.t[1])
def __repr__(self):
return str(t)
# now you can declare:
all_values = [
({'x1': 1, 'y1': 2}, 'str1'),
({'x2': 1, 'y2': 2}, 'str2'),
({'x2': 1, 'y2': 2}, 'str2'),
({'x3': 1, 'y3': 2}, 'str3'),
({'x3': 1, 'y3': 2}, 'str3')
]
#create your objects and put them in a list
all_vals = []
map(lambda x: all_vals.append(Tup(x)), all_values)
print all_vals # [({'y1': 2, 'x1': 1}, 'str1'), ({'x2': 1, 'y2': 2}, 'str2'), ({'x2': 1, 'y2': 2}, 'str2'), ({'x3': 1, 'y3': 2}, 'str3'), ({'x3': 1, 'y3': 2}, 'str3')]
# and use Set for uniqueness
from sets import Set
print Set(all_vals) # Set([({'x3': 1, 'y3': 2}, 'str3'), ({'x3': 1, 'y3': 2}, 'str3'), ({'x3': 1, 'y3': 2}, 'str3')])
对于那些认为尺寸很重要的人来说,另一个更短的版本;)
res = []
for a in all_values:
if a[1] not in map(lambda x: x[1], res):
res.append(a)
print res
答案 4 :(得分:0)
如果您不关心订购,请使用dict
formattedValues = {}
# Use with reveresed if you want the first duplicate to be kept
# Use without reveresed if you want the last duplicated
for v in reversed(allValues):
formattedValues[ v[1] ] = v
如果订购 是一个问题,请使用OrderedDict
from collections import OrderedDict
formattedValues = OrderedDict()
for v in reversed(allValues):
formattedValues[ v[1] ] = v
答案 5 :(得分:0)
itertools Recipes有一个函数 unique_everseen ,它将根据传入的键返回传入的iterable中唯一项的迭代器,如果你想要一个列表作为结果将结果传递给list()但是如果有大量数据,那么如果可以节省内存则最好迭代。
from itertools import ifilterfalse
from operator import itemgetter
all_values = [
({'x1': 1, 'y1': 2}, 'str1'),
({'x2': 1, 'y2': 2}, 'str2'),
({'x5': 8, 'ab': 7}, 'str2'),
({'x3': 1, 'y3': 2}, 'str3')]
def unique_everseen(iterable, key=None):
"List unique elements, preserving order. Remember all elements ever seen."
# unique_everseen('AAAABBBCCDAABBB') --> A B C D
# unique_everseen('ABBCcAD', str.lower) --> A B C D
seen = set()
seen_add = seen.add
if key is None:
for element in ifilterfalse(seen.__contains__, iterable):
seen_add(element)
yield element
else:
for element in iterable:
k = key(element)
if k not in seen:
seen_add(k)
yield element
print list(unique_everseen(all_values, itemgetter(1)))
输出
[({'y1': 2, 'x1': 1}, 'str1'), ({'x2': 1, 'y2': 2}, 'str2'), ({'x3': 1, 'y3': 2}, 'str3')]