从Dict(python)中的itemgetter查找值

问题描述 投票:1回答:3

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

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中的值创建排序?

python sorting dictionary tuples
3个回答
4
投票

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

只需使用传递到keylambda值直接访问字典。它是一个元组,所以添加索引:

sortedView = sorted(connectionsList, key=lambda k: valuesDict[k[0]] + valuesDict[k[1]])

key参数必须是一个可调用对象,它接受一个参数(其中一个项被排序),并返回您实际排序的值。 itemgetter()根据您调用它的对象的索引返回结果; itemgetter(0)(some_tuple)将从传入的元组返回第一个元素。

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

演示:

>>> 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()对象;元组已经以0, 1顺序提供,因此您可以在不使用排序键的情况下获得相同的排序顺序。


2
投票

如果你想使用valuesDict查找sumitemgetter中的键,你必须做这样的事情:

>>> 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 loopup:

>>> 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')]

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


0
投票

你可以尝试这样的事情:

首先收集列表中的sum和tuple:

lambda

它会给:

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))))
© www.soinside.com 2019 - 2024. All rights reserved.