我收到一个字典作为输入,并希望返回字典值在该字典范围内唯一的键列表。
我将用一个例子来澄清。假设我的输入是字典a,构造如下:
a = dict()
a['cat'] = 1
a['fish'] = 1
a['dog'] = 2 # <-- unique
a['bat'] = 3
a['aardvark'] = 3
a['snake'] = 4 # <-- unique
a['wallaby'] = 5
a['badger'] = 5
我期望的结果是['dog', 'snake']
。
有很明显的蛮力方法来实现这一目标,但我想知道是否有一种巧妙的Python方式来完成工作。
答案 0 :(得分:13)
我认为如果dict太大会有效的方式
countMap = {}
for v in a.itervalues():
countMap[v] = countMap.get(v,0) + 1
uni = [ k for k, v in a.iteritems() if countMap[v] == 1]
答案 1 :(得分:5)
请注意,这实际上是一个暴力:
l = a.values()
b = [x for x in a if l.count(a[x]) == 1]
答案 2 :(得分:5)
这是一个只需要遍历dict的解决方案:
def unique_values(d):
seen = {} # dict (value, key)
result = set() # keys with unique values
for k,v in d.iteritems():
if v in seen:
result.discard(seen[v])
else:
seen[v] = k
result.add(k)
return list(result)
答案 3 :(得分:4)
>>> b = []
>>> import collections
>>> bag = collections.defaultdict(lambda: 0)
>>> for v in a.itervalues():
... bag[v] += 1
...
>>> b = [k for (k, v) in a.iteritems() if bag[v] == 1]
>>> b.sort() # optional
>>> print b
['dog', 'snake']
>>>
答案 4 :(得分:2)
稍微冗长一点,但只需要一次通过:
revDict = {}
for k, v in a.iteritems():
if v in revDict:
revDict[v] = None
else:
revDict[v] = k
[ x for x in revDict.itervalues() if x != None ]
(我希望它有效,因为我不能在这里测试)
答案 5 :(得分:2)
子类化怎么样?
class UniqueValuesDict(dict):
def __init__(self, *args):
dict.__init__(self, *args)
self._inverse = {}
def __setitem__(self, key, value):
if value in self.values():
if value in self._inverse:
del self._inverse[value]
else:
self._inverse[value] = key
dict.__setitem__(self, key, value)
def unique_values(self):
return self._inverse.values()
a = UniqueValuesDict()
a['cat'] = 1
a['fish'] = 1
a[None] = 1
a['duck'] = 1
a['dog'] = 2 # <-- unique
a['bat'] = 3
a['aardvark'] = 3
a['snake'] = 4 # <-- unique
a['wallaby'] = 5
a['badger'] = 5
assert a.unique_values() == ['dog', 'snake']
答案 6 :(得分:0)
这是另一种变体。
>>> import collections
>>> inverse= collections.defaultdict(list)
>>> for k,v in a.items():
... inverse[v].append(k)
...
>>> [ v[0] for v in inverse.values() if len(v) == 1 ]
['dog', 'snake']
我偏爱这个,因为倒置字典是一种常见的设计模式。
答案 7 :(得分:-1)
你可以这样做(只计算每个值的出现次数):
def unique(a):
from collections import defaultdict
count = defaultdict(lambda: 0)
for k, v in a.iteritems():
count[v] += 1
for v, c in count.iteritems():
if c <= 1:
yield v
答案 8 :(得分:-2)
使用嵌套列表推导!
print [v[0] for v in
dict([(v, [k for k in a.keys() if a[k] == v])
for v in set(a.values())]).values()
if len(v) == 1]