【问题标题】:How to operate on nested dictionary in python 3.x?如何在 python 3.x 中对嵌套字典进行操作?
【发布时间】:2017-07-15 15:43:33
【问题描述】:

我被这个问题困住了,你能解决这个挑战吗?我们开始吧!

我们在一个二级字典中表示一系列比赛中的球员得分,如下所示:

{'match1':{'player1':57, 'player2':38}, 'match2':{'player3':9, 'player1':42}, 'match3':{'player2':41, 'player4':63, 'player3':91}}

每场比赛都由一个字符串标识,每个玩家也是如此。分数都是整数。与比赛相关的名字不是固定的(这里它们是'match1'、'match2'、'match3'),球员的名字也不是固定的。玩家不需要在所有比赛中记录得分。

定义一个 Python 函数orangecap(d) 读取这种形式的字典 d 并识别总分最高的玩家。您的函数应该返回一对 (playername,topscore),其中 playername 是一个字符串,即得分最高的玩家的名字,而 topscore 是一个整数,即 playername 的总分。

输入将使得最高总分永远不会出现平局。

例如:

>>> orangecap({'match1':{'player1':57, 'player2':38}, 'match2':{'player3':9, 'player1':42}, 'match3':{'player2':41, 'player4':63, 'player3':91}})
('player3', 100)

>>> orangecap({'test1':{'Ashwin':84, 'Kohli':120}, 'test2':{'ashwin':59, 'Pujara':42}})
('Kohli', 120)

【问题讨论】:

  • 挑战?这是一场(正在运行的)编程竞赛吗?
  • 请更具体地说明您面临的问题。我们不会为您解决问题。
  • 我刚刚在 stackoverflow 上偶然发现了这个问题的多个实例。有什么事吗?
  • 似乎是一个任务或什么 o.0 ?

标签: python python-3.x sorting dictionary nested


【解决方案1】:

pandas 真的很简单:

In [78]: d
Out[78]: 
{'match1': {'player1': 57, 'player2': 38},
 'match2': {'player1': 42, 'player3': 9},
 'match3': {'player2': 41, 'player3': 91, 'player4': 63}}

In [79]: pd.DataFrame(d).sum(axis=1).idxmax()
Out[79]: 'player3'

In [80]: pd.DataFrame(d).sum(axis=1).max()
Out[80]: 100.0

首先将其转换为 DataFrame,然后对列求和,然后找到最大值:)

【讨论】:

  • 如何将 ipython 代码放在这里作为答案?显示 In[]Out[] 的东西?
  • 我发现使用 anaconda 和 spyder 最适合回答堆栈溢出问题。然后您可以从 spyder3 中的 ipython 控制台“复制(原始文本)”
  • 作为答案看起来更好更酷:)我会看看 spyder3,谢谢!
  • @juanpa.arrivillaga 例如在可能不是那么微不足道的窗口上
  • @SebastianWozny 啊,是的。 cmd.exe 是个笑话。我会建议找到一个不糟糕的终端模拟器,但这对于 Windows 来说可能不是那么简单。
【解决方案2】:

您可以轻松地使用运行计数器先计算分数:

from collections import Counter

def orangecap(d):
    total = Counter()
    for match_result in d.values():
        total.update(match_result)
    return total.most_common(1)[0]

这里Counter.update(iterable) 将增加提到的玩家的计数器。 Counter.most_common(n) 指定我们想要第一个最常见的元素。这将返回一个列表,我们选择第一个元组。

>>> orangecap(d)
('player3', 100)

【讨论】:

  • 那是完美的威廉!
【解决方案3】:

我建议使用 Willem Van Onsem 答案,但如果您不想导入,那么这里是另一种选择。

data = {
    'match1': {
        'player1': 57,
        'player2': 38},
    'match2': {
        'player3': 9,
        'player1': 42},
    'match3': {
        'player2': 41,
        'player4': 63,
        'player3': 91}
    }


def orangecap(data):
    totals = {}
    for d in data.values():
        for k, v in d.items():
            totals[k] = totals.setdefault(k, 0) + v

    return max(totals.items(), key = lambda t:t[1])

>>> orangecap(data)
('player3', 100)

【讨论】:

  • 我认为 op 想要该玩家的总分:P
  • 啊,没看到总数。谢谢
  • 它是最好的答案之一。非常感谢。实际上需要计算总分作为输出。在这种情况下,输出应该是 match3 和 match 2 的 91+9。所以结果应该是 100。但它显示的是 91。你可以对此进行编辑吗?
  • 我已经编辑了我的答案。我之前的回答没有把每个玩家的分数加起来然后找到最大值。
【解决方案4】:
import operator

def orangecap(d):
    players = {}    
    for dict in d.values():
        for player in dict:
            if player in players:
               players[player] += dict[player]
            else:
               players[player] = dict[player]

    scores = sorted(players.items(), key = operator.itemgetter(1), reverse = True)
    return scores[0]

#Credits to  Willem Van Onsem for his various suggestions

【讨论】:

  • 你可以试试collections.defaultdict:)
  • 此外,sorted(..)不能内联(尤其是因为字典没有顺序)而且您也不必排序:您可以使用max
  • 嗯,很好发现@WillemVanOnsem,这段代码永远不会工作。您的意思是 inplace 而不是 inline。 :( 你应该修复代码,否则你会被否决。
  • @SebastianWozny:确实是的(英语不是我的母语)。
  • 我很抱歉,我以为我写了别的东西:P
【解决方案5】:

一些代码与functools.reduce打高尔夫球:

from functools import reduce
from collections import Counter

v = reduce(lambda x, y: x.update(y) or x, d.values(), Counter()).most_common(1)[0])
print(v)
# ('player3', 100)

【讨论】:

    猜你喜欢
    • 2015-12-02
    • 1970-01-01
    • 2023-03-14
    • 2016-10-31
    • 1970-01-01
    • 1970-01-01
    • 2019-02-08
    • 2020-04-29
    相关资源
    最近更新 更多