如何从列表中隔离Python字典以进行比较?

时间:2014-10-30 15:56:56

标签: python list dictionary shelve

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

搁架应该只存储每个玩家的高分;对于名为" Joe"的人来说,不应该得分。例如。

不幸的是,我无法弄清楚如何将dict与dicts(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

任何提示都将不胜感激!

3 个答案:

答案 0 :(得分:1)

如果您没有其他理由使用词典列表,只需使用词典(甚至是简单的词典)就可以大大简化您的代码。假设你的架子看起来像

{
   "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

请注意,如果书架只包含&#34; user_data&#34;,您可以摆脱此级别并直接将您的dicts存储在书架本身。此外,如果你只有得分保存,你可以把你的词典转换成一个简单的词典,即:

=&GT;你的架子:

{
  "joe": : 2999, 
  "walt": 1784, 
  "bunny": 87441, 
  # etc
}

=&GT;你的代码:

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

编辑:以下代码JustWorks(tm)on 2.7.3:

# 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'}}}

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

我用你的剧本玩了一点。它工作正常,但当我看到货架上的东西时,我发现:

{ 'player_data' : [ { 'score': 10, 'name': 'joe' }, { 'score': 5, 'name': 'jim'} ] }

它是一个字典(搁置本身),其中包含一个dicts列表,而该列表又只有2个属性。

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

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

{ 'joe': 10, 'jim' : 5 }

或者如果您以后想要为每个玩家添加其他属性:

{ 'joe': { 'score': 10}, 'jim' : { 'score': 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

这只是bruno desthuilliers答案的一个细微变化,但我测试了id和:

  • 正确保留并显示每位用户更高的分数
  • 只保留较高分数的版本不需要writeback=true,因为更改的内容只是货架的顶级元素