Python数据结构推荐与改进

目前有一个字典形式的数据结构,其中每个值都是一个包含数字值的数据列表。这些数字列表中的每一个都包含了可以使用 SQL 术语来称之为主键的什么东西,包含了前三个值:年份、球员标识符和球队标识符。这是字典中的键。因此,可以通过为年份、球员 ID和球队 ID传递值来获取唯一行,如下所示:

statline = stats[(2001, 'SEA', 'suzukic01')]

这会产生类似这样的结果:

[305, 20, 444, 330, 45]

希望这个数据结构可以快速地按这三个键中的任何一个进行求和:因此,可以轻松地通过传递年份、球员 ID和球队 ID中的一个,然后传递索引来切片数字列表中给定索引处的总和。希望能够做类似这样的事情:

hr_total = stats[year=2001, idx=3]

其中,索引 3 对应于检索到的数字列表中的第三列。

2、解决方案
有以下几种解决方案:

  • 解决方案一:将数据放入 SQLite 中,并使用其关系引擎来完成这项工作。甚至可以创建一个内存数据库,而无需触及磁盘。
  • 解决方案二:查阅有关数据仓储的任何书籍。学习星型模式设计。具有多个维度:年、球员、球队。有一个事实:得分。希望有一个这样的结构。然后希望创建一个这样的维度索引集。
years = collections.defaultdict(list)
players = collections.defaultdict(list)
teams = collections.defaultdict(list)

事实表可以是这个 collections.namedtuple。可以像这样使用它。

class ScoreFact(object):
    def __init__(self, year, player, team, score):
        self.year = year
        self.player = player
        self.team = team
        self.score = score
        years[self.year].append(self)
        players[self.player].append(self)
        teams[self.team].append(self)

现在可以找到给定维度值中的所有项。它是一个附加到维度值上的简单列表。year[‘2001’] 是给定年份的所有得分。player[‘SEA’] 是给定球员的所有得分。等等。可以简单地使用 sum() 将它们相加。多维查询类似于这样。

[x for x in players['SEA'] if x.year == '2001']
  • 解决方案三:语法 stats[year=2001, idx=3] 是无效的 Python,无法用那些方括号和“关键字参数”让它工作;需要有函数或方法调用才能接受关键字参数。因此,假设将其变成一个函数,像这样调用 wells(stats, year=2001, idx=3)。想象 idx 参数是强制性的(给定调用这是非常奇怪的,但是没有给出任何可能意味着省略 idx 的迹象),并且必须存在 year、playerid 和 teamid 中的恰好一个。使用当前的数据结构,已经可以实现 wells:
def wells(stats, year=None, playerid=None, teamid=None, idx=None):
    if idx is None: raise ValueError('idx must be specified')
    specifiers = [(i, x) for x in enumerate((year, playerid, teamid)) if x is not None]
    if len(specifiers) != 2:
        raise ValueError('Exactly one of year, playerid, teamid, must be given')
    ikey, keyv = specifiers[0]
    return sum(v[idx] for k, v in stats.iteritems() if k[ikey] == keyv)

当然,这是 stats 大小的 O(N)——它必须检查其中的每个条目。请使用此简单实现作为基准来衡量正确性和性能。另一种解决方案(使用起来要快得多,但需要花费大量时间准备)是在 stats 旁边放置三个列表字典(分别用于 year、playerid、teamid),每个条目都表示(或复制,但认为按完整键指示可能就足够了)所有与该 ikey / keyv 对匹配的 stats条目。但目前尚不清楚是否可能为时过早地实现,因此请先尝试使用简单的想法!-)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值