关于多维Python dicts的数学运算

时间:2016-09-27 18:04:28

标签: python dictionary

我正在移植PHP中的一些代码,这些代码遍历一些数据库结果,并为棒球联盟的团队构建一个二维的输赢组。这是PHP中的代码

    foreach ($results as $result) {
        $home_team = $result['Game']['home_team_id'];
        $away_team = $result['Game']['away_team_id'];

        if (!isset($wins[$home_team][$away_team])) $wins[$home_team][$away_team] = 0;
        if (!isset($wins[$away_team][$home_team])) $wins[$away_team][$home_team] = 0;
        if (!isset($losses[$home_team][$away_team])) $losses[$home_team][$away_team] = 0;
        if (!isset($losses[$away_team][$home_team])) $losses[$away_team][$home_team] = 0;

        if ($result['Game']['home_score'] > $result['Game']['away_score']) {
            $wins[$home_team][$away_team]++;
            $losses[$away_team][$home_team]++;
        } else {
            $wins[$away_team][$home_team]++;
            $losses[$home_team][$away_team]++;
        }
    }

$results是一个包含数据库查询结果的数组

(编辑添加我已经拥有的Python代码)

现在我有了这个但是在Python中。 results包含一系列Sqlalchemy结果对象

from sqlalchemy import Column, create_engine, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker


Base = declarative_base()
engine = create_engine('postgresql://stats:st@ts=Fun@localhost/ibl_stats')
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()


class Game(Base):
    __tablename__ = 'games'

    id = Column(Integer, primary_key=True)
    week = Column(Integer)
    home_score = Column(Integer)
    away_score = Column(Integer)
    home_team_id = Column(Integer, ForeignKey('franchises.id'))
    away_team_id = Column(Integer, ForeignKey('franchises.id'))


class Franchise(Base):
    __tablename__ = 'franchises'

    id = Column(Integer, primary_key=True)
    nickname = Column(String(3))
    name = Column(String(50))
    conference = Column(String(10))
    division = Column(String(10))
    ip = Column(Integer)

# Loop through our standings building up the breakdown results
results = session.query(Game).all()
wins = dict()
losses = dict()

for result in results:
    home_team = result.home_team_id
    away_team = result.away_team_id

    if result.home_score > result.away_score:
        wins[home_team][away_team] += 1
        losses[away_team][home_team] += 1
    else:
        wins[away_team][home_team] += 1
        losses[home_team][away_team] += 1

因此,当我运行此代码时,我收到以下错误:

(venv)vagrant@ibl:/vagrant/scripts$ python playoff_odds.py
Traceback (most recent call last):
  File "playoff_odds.py", line 45, in <module>
    wins[home_team][away_team] += 1
KeyError: 1

之前我做了一些搜索,它开始涉及“自动修复”的概念,这是PHP默认执行的操作,但Python没有。

那么如何在Python代码中复制相同的行为呢?

3 个答案:

答案 0 :(得分:2)

Python's built-in dict class can be subclassed to implement autovivificious dictionaries simply by overriding the missing() method ,但这只是解决方案的一部分。如果您只是在维基百科链接中实现Tree示例并执行以下操作:

wins = Tree()

wins['team_a']['team_b'] += 1

您遇到了TypeError: unsupported operand type(s) for +=: 'Tree' and 'int',因为wins['team_a']['team_b']的示例代码也会自动输入Tree

鉴于:

wins = Tree()

wins['team_a']['team_b'] = 1

会正确分配值1(因为它是重新分配,而不是对现有类型值的操作)。

该解决方案将子类化以实现自动生成,以确保叶元素是可以操作的整数。以下内容应该为您解决这个问题,或者至少让您开始:

以下内容应该有所帮助,或者至少可以帮助您:

from collections import defaultdict

def autovivify(levels=1, final=dict):
    return (defaultdict(final) if levels < 2
        else defaultdict(lambda: autovivify(levels - 1, final)))

wins = autovivify(2, int)
losses = autovivify(2, int)

wins['team_a']['team_b'] += 1
losses['team_b']['team_a'] += 1

wins['team_b']['team_c'] += 1
losses['team_c']['team_b'] += 1

wins['team_a']['team_c'] += 1
losses['team_c']['team_a'] += 1

wins['team_a']['team_b'] += 1
losses['team_b']['team_a'] += 1

print(wins['team_a']) # outputs defaultdict(<type 'int'>, {'team_b': 2, 'team_c': 1})

来源: http://blogs.fluidinfo.com/terry/2012/05/26/autovivification-in-python-nested-defaultdicts-with-a-specific-final-type/

autovivify函数将确保第一个赋值(team_a)将为您提供另一个自动生成树,第二个赋值(team_b)将为您提供整数。从那里,您的+= 1将继续增加0的初始值。

答案 1 :(得分:1)

我想我可能会在这里使用namedtuples,但很难从这个片段中分辨出来。

如果您想了解如何编写更多Pythonic代码的材料,我建议您查看Raymond Hettinger的视频,特别是

&#34;美观易懂代码的最佳实践&#34;和 &#34;将代码转换为美丽的,惯用的Python&#34;:

http://pyvideo.org/speaker/raymond-hettinger.html

答案 2 :(得分:1)

这个问题有很多解释。例如,我将使用以下字典模拟结果:

>>> result = {'Game':{'home_team':{'score':20,'id':1}, 'away_team':{'score':15,'id':2}}}
>>> print result['Game']
{'home_team': {'score': 20, 'id': 1}, 'away_team': {'score': 15, 'id': 2}}
>>> print result['Game']['home_team']
{'score': 20, 'id': 1}
>>> print result['Game']['away_team']['score']
15

有很多方法可以模拟你的代码,上面只是其中之一。当然,代码不会执行php代码所做的事情,只是显示了一种访问数据的方法。