从Dict(python)中的itemgetter查找值

时间:2017-12-29 13:28:41

标签: python sorting dictionary tuples

我有一个我正在尝试排序的元组列表。元组包含字符串:

connectionsList = [('C', 'B'), ('A', 'C'), ('D', 'B'), ('C','D')]

元组中的字符串具有存储在dict中的数值:

valuesDict = {'A':3, 'B':5, 'C':1, 'D':2}

我想要做的是按照元组dict中值的总和对列表进行排序。这个玩具示例的所需输出将是:

[(C,D), (A,C), (C,B), (D,B)]

的总和为:

[3, 4, 6, 7]

使用itemgetter,我可以按位置按字母顺序排序:

sortedView = sorted(connectionsList, key=itemgetter(0,1))

但是,我在查找dict中itemgetter的值时遇到问题。运行这个:

sortedView = sorted(connectionsList, key=valuesDict[itemgetter(0)] + valuesDict[itemgetter(1)])

给出 KeyError的dict错误:operator.itemgetter(0)

如何根据dict中的值创建排序?

3 个答案:

答案 0 :(得分:4)

不要使用itemgetter个实例;你需要打电话给他们,但他们在这里有点过分。

只需使用传递到key的{​​{1}}值直接访问字典即可。它是一个元组,所以添加索引:

lambda

sortedView = sorted(connectionsList, key=lambda k: valuesDict[k[0]] + valuesDict[k[1]]) 参数必须是可调用对象,它接受一个参数(其中一个项目正在排序),并返回您实际排序的值。 key根据您调用它的对象的索引返回结果; itemgetter()将返回传入的元组中的第一个元素。

lambda也可以这样做,在上面的解决方案中,lambda返回给定元组的所需总和。

演示:

itemgetter(0)(some_tuple)

您还可以将您的元组视为任意长度的序列。如果您还考虑了元组中并非所有值都是>>> connectionsList = [('C', 'B'), ('A', 'C'), ('D', 'B'), ('C','D')] >>> valuesDict = {'A':3, 'B':5, 'C':1, 'D':2} >>> sorted(connectionsList, key=lambda k: valuesDict[k[0]] + valuesDict[k[1]]) [('C', 'D'), ('A', 'C'), ('C', 'B'), ('D', 'B')] 映射的有效键(取而代之的是valuesDict)的可能性,您还可以获得以下解决方案:

0

这更通用,更健壮。

您也不需要按字母顺序使用sortedView = sorted(connectionsList, key=lambda k: sum(valuesDict.get(v, 0) for v in k)) 对象;元组已经按itemgetter()顺序提供,因此您可以使用排序键获得相同的排序顺序,而无需

答案 1 :(得分:2)

如果您想使用valuesDictsumitemgetter中查找密钥,则必须执行以下操作:

>>> from operator import itemgetter

>>> connectionsList = [('C', 'B'), ('A', 'C'), ('D', 'B'), ('C','D')]
>>> valuesDict = {'A':3, 'B':5, 'C':1, 'D':2}

>>> idx = 0
>>> sum(itemgetter(*itemgetter(0, 1)(connectionsList[idx]))(valuesDict))
6

connectionsList[idx]是将传递给key函数的当前元素。因此,您需要对此进行转换,以便实际的键功能仅需要当前元素作为参数:

>>> def keyfunc(cur_element):
...     return sum(itemgetter(*itemgetter(0, 1)(cur_element))(valuesDict))
>>> sorted(connectionsList, key=keyfunc)
[('C', 'D'), ('A', 'C'), ('C', 'B'), ('D', 'B')]

然而,与没有itemgetter的解决方案相比,这并不是真的可读:

>>> def keyfun(cur_element):
...     i1, i2 = cur_element
...     return valuesDict[i1] + valuesDict[i2]
>>> sorted(connectionsList, key=keyfunc)
[('C', 'D'), ('A', 'C'), ('C', 'B'), ('D', 'B')]

所以在这种情况下你可能不应该使用itemgetter,因为它涉及更多的函数调用,结果函数不是那么好。

如果valuesDict字典中可能缺少部分密钥,则应将[]循环替换为get次调用:

>>> def keyfun(cur_element):
...     i1, i2 = cur_element
...     return valuesDict.get(i1, 0) + valuesDict.get(i2, 0)
>>> sorted(connectionsList, key=keyfunc)
[('C', 'D'), ('A', 'C'), ('C', 'B'), ('D', 'B')]

注意我通常更喜欢正常def函数而不是lambda s当它们变得更复杂时,但这是一个品味问题。在这种情况下,很容易将它们翻译为lambda s。

答案 2 :(得分:0)

您可以尝试这样的事情:

首先在列表中收集总和和元组:

connectionsList = [('C', 'B'), ('A', 'C'), ('D', 'B'), ('C','D')]

valuesDict = {'A':3, 'B':5, 'C':1, 'D':2}


tuple_sum=[]
for i in connectionsList:
    tuple_sum.append((valuesDict.get(i[0])+valuesDict.get(i[1]),i))

它会给出:

[(6, ('C', 'B')), (4, ('A', 'C')), (7, ('D', 'B')), (3, ('C', 'D'))]

现在对它进行排序并仅采用嵌套元组:

print(list(map(lambda x:x[1],sorted(tuple_sum))))

输出:

[('C', 'D'), ('A', 'C'), ('C', 'B'), ('D', 'B')]