如何将Python字典从列表中分离出来进行比较?

如何将Python字典从列表中分离出来进行比较?,python,list,dictionary,shelve,Python,List,Dictionary,Shelve,我有一个Python函数,它以玩家的名字和分数作为参数,并确定这是否是玩家的最高分数。它通过将参数与搁置对象进行比较来实现 架子上应该只存储每个玩家的高分;例如,对于一个叫“乔”的人,不应该有分数 不幸的是,我不知道如何将dict从dict列表(shelf)中分离出来,以便与传入的播放器dict进行比较 这是我的密码: import shelve import os def highscore(player_name, player_score): """ Function

我有一个Python函数,它以玩家的名字和分数作为参数,并确定这是否是玩家的最高分数。它通过将参数与搁置对象进行比较来实现

架子上应该只存储每个玩家的高分;例如,对于一个叫“乔”的人,不应该有分数

不幸的是,我不知道如何将dict从dict列表(shelf)中分离出来,以便与传入的播放器dict进行比较

这是我的密码:

import shelve
import os


def highscore(player_name, player_score):
    """
    Function to return the high score from our
    persistent storage of score records for a given
    person.
    """
    # Get our working directory
    working_dir = os.getcwd()
    # Create our shelf object for a player
    highscore_fn = os.path.join(working_dir, 'highscore.shelve')
    # Set our player info
    player = {'name': player_name, 'score': player_score}

    with shelve.open(highscore_fn, writeback=True) as shelf:
        # Check if any records exist in the shelf
        if len(shelf) == 0:
            # Assign the shelf to an empty list
            shelf['player_data'] = []
            # Append player data to shelf
            shelf['player_data'].append(player)
            # Current high score for player
            high_score = player.get('score')
        else:
            # Loop through our player data list
            for data in shelf['player_data']:
                # Check to see if we have data for a player
                if player['name'] in data['name']:
                    existing_record = data
                    # Compare the player's new score against previous score
                    if player.get('score') > existing_record.get('score'):
                        high_score = player.get('score')
                        # Update our record for the player
                        existing_record.update(player)
                    else:
                        high_score = existing_record.get('score')
                else:
                    high_score = player.get('score')
                    shelf['player_data'].append(player)

    # Return the high score
    return high_score

任何提示都将不胜感激

如果您没有其他理由使用dict列表,那么仅使用dict of dict(甚至是简单的dict)将大大简化您的代码。假设你的架子看起来像

{
   "user_data": { 
      "joe": {"score": 2999, "name":"joe"}, 
      "walt": {"score": 1784, "name":"walt"}, 
      "bunny": {"score": 87441, "name":"bunny"}, 
      # etc
      },
}
那么您的代码将如下所示:

player = {'name': player_name, 'score': player_score}
high_score = player_score
with shelve.open(highscore_fn, writeback=True) as shelf:
    user_data = shelf["user_data"]
    # Check if any records exist in the shelf
    found = user_data.get(player_name)
    if found:
        if found["score"] < player_score:
            user_data[player_name] = player
        else:
            high_score = found["score"]
    else:
        user_data[player_name] = player
    shelf["user_data"] = user_data

return high_score
=>您的代码:

high_score = player_score
with shelve.open(highscore_fn, writeback=True) as shelf:
    # Check if any records exist in the shelf
    found = shelf.get(player_name, 0)
    if found > player_score:
        high_score = found
    else:
        shelf[player_name] = player_score

return player_score
编辑:2.7.3中的以下代码JustWorks(tm):

# scores.py
import shelve

DATA = {
    "user_data": { 
        "joe": {"score": 2999, "name":"joe"}, 
        "walt": {"score": 1784, "name":"walt"}, 
        "bunny": {"score": 87441, "name":"bunny"}, 
        # etc
        },
    }


class Score(object):
    def __init__(self, path):
        self.path = path

    def init_data(self, data):
        shelf = shelve.open(self.path)
        shelf["user_data"] = data["user_data"]
        shelf.close()

    def read_data(self):
        d = {}
        shelf = shelve.open(self.path)
        d["user_data"] = shelf["user_data"]
        shelf.close()
        return d

    def highscore(self, name, score):
        player = {'name': name, 'score': score}
        high_score = score
        shelf = shelve.open(self.path)
        user_data = shelf["user_data"]
        found = user_data.get(name)
        if found:
            if found["score"] < score:
                user_data[name] = player
            else:
                high_score = found["score"]
        else:
            user_data[name] = player
        shelf["user_data"] = user_data
        shelf.sync()
        shelf.close()
        return high_score


>>> import scores
>>> s = scores.Score("scores.dat")
>>> s.init_data(scores.DATA)
>>> s.read_data()
{'user_data': {'walt': {'score': 1784, 'name': 'walt'}, 'joe': {'score': 2999, 'name': 'joe'}, 'bunny': {'score': 87441, 'name': 'bunny'}}}
>>> s.highscore("walt", 10000)
10000
>>> s.read_data()
{'user_data': {'walt': {'score': 10000, 'name': 'walt'}, 'joe': {'score': 2999, 'name': 'joe'}, 'bunny': {'score': 87441, 'name': 'bunny'}}}
#scores.py
进口货架
数据={
“用户数据”:{
“乔”:{“分数”:2999,“姓名”:“乔”},
“沃尔特”:{“分数”:1784,“名字”:“沃尔特”},
“兔子”:{“分数”:87441,“名字”:“兔子”},
#等
},
}
班级成绩(对象):
定义初始化(自身,路径):
self.path=path
def初始数据(自身,数据):
shelf=shelve.open(self.path)
工具架[“用户数据”]=数据[“用户数据”]
关闭
def读取_数据(自身):
d={}
shelf=shelve.open(self.path)
d[“用户数据”]=工具架[“用户数据”]
关闭
返回d
def高分(自我、姓名、分数):
玩家={'name':name,'score':score}
高分=分数
shelf=shelve.open(self.path)
用户数据=工具架[“用户数据”]
found=user\u data.get(名称)
如果发现:
如果找到[“分数”]<分数:
用户_数据[名称]=播放器
其他:
高分=找到[“分数”]
其他:
用户_数据[名称]=播放器
工具架[“用户数据”]=用户数据
shelf.sync()
关闭
返回高分
>>>输入分数
>>>s=分数.Score(“分数.dat”)
>>>s.init_数据(分数数据)
>>>美国read_数据()
{'user_data':{'walt':{'score':1784,'name':'walt'},'joe':{'score':2999,'name':'joe'},'bunny':{'score':87441,'name':'bunny'}
>>>s.highscore(“沃尔特”,10000)
10000
>>>美国read_数据()
{'user_data':{'walt':{'score':10000,'name':'walt'},'joe':{'score':2999,'name':'joe'},'bunny':{'score':87441,'name':'bunny'}

编辑以下是解决我问题的重构代码:

import shelve
import os


def highscore(name, score):
    """
    Function to return the high score from our
    persistent storage of score records for a given
    person.
    """
    # Get our working directory
    working_dir = os.getcwd()
    # Create our shelf object for a player
    highscore_fn = os.path.join(working_dir, 'highscore.shelve')
    # Open our shelf
    with shelve.open(highscore_fn, writeback=True) as shelf:
        # Check if player exists in shelf
        if name in shelf:
            # Check if score is greater than existing score
            if score > shelf[name]:
                # Assign our new high score
                high_score = score
                # Assign the value of player to our shelf
                shelf[name] = score
            else:
                # Existing high score stands for player
                high_score = shelf[name]
        else:
            # Assign the player to the shelf
            shelf[name] = score
            # Assign the high score to the player score
            high_score = score

    return high_score

我和你的剧本玩了一点。它很好用,但当我查看架子上的东西时,我发现:

{ 'player_data' : [ { 'score': 10, 'name': 'joe' }, { 'score': 5, 'name': 'jim'} ] }
它有一个字典(书架本身),其中包含一个目录列表,而目录列表又只有两个属性

在你的代码中,很明显你想要的只是一个玩家的属性(这里是[高分])(这里是一个名字)

我的建议是重写它,除非搁置的格式是公共API的一部分,以便搁置成为:

{ 'joe': 10, 'jim' : 5 }
player = {'name': player_name, 'score': player_score}

with shelve.open(highscore_fn) as shelf:
    high_score = shelf[player_name] if shelf.has_key(player_name) else None
    if (high_score is None) or (high_score < player_score):
        high_score = player_score
        shelf[player_name] = high_score
    shelf.close()

return high_score
或者,如果以后要为每个玩家添加其他属性:

{ 'joe': { 'score': 10}, 'jim' : { 'score': 5} }
这样,一切都会变成:

{ 'joe': 10, 'jim' : 5 }
player = {'name': player_name, 'score': player_score}

with shelve.open(highscore_fn) as shelf:
    high_score = shelf[player_name] if shelf.has_key(player_name) else None
    if (high_score is None) or (high_score < player_score):
        high_score = player_score
        shelf[player_name] = high_score
    shelf.close()

return high_score
player={'name':player_name,'score':player_score}
带搁板。打开(高分)作为搁板:
high_score=架子[player_name],如果架子上有_键(player_name),否则无
如果(高分为无)或(高分<球员分数):
高分=球员得分
架子[玩家姓名]=高分
关闭
返回高分
这只是bruno desthuilliers答案的一个微小变化,但我测试了id和:

  • 它正确地保留并显示每个用户的较高分数
  • 只保留较高分数的版本不需要
    writeback=true
    ,因为所更改的只是工具架的顶层元素

您能否展示一个例子,将一个dict从dict列表(shelf)中分离出来,以便与传入的播放器dict进行比较?是否有可能重复使用dict列表而不是dict的dict?另外(完全不相关),您决不能依赖于
os.getcwd()
要计算应用程序数据的路径-“当前工作目录”不是指“您的代码文件所在的目录”,而是指“用户启动程序时所在的目录”(假设部分代码没有将其更改为其他任何内容…).你的书架上除了
player\u data
dicts列表之外还有其他对象吗?因此,这不是我所需要的,尽管它让我朝着正确的方向思考。如果为同一名玩家输入了后续分数,则不会存储该玩家的高分。@PatrickBeeson:第一个示例中确实有一个输入错误和一个缺失。FWIW我不知道您正在使用哪个Python版本,但在我这里的版本(2.7.3)上,
带有shelve.open()
会引发“AttributeError:DbfilenameShelf实例没有属性‘exit’”。