【问题标题】:Summing a tuple-of-tuples and a nested dict对元组和嵌套字典求和
【发布时间】:2016-09-17 10:21:40
【问题描述】:

我有可以以两种不同形式表示的数据(出于历史原因,我不会深入探讨)。第一个是tuples 的tuple

t = (('a', 'x', 3), 
('a', 'f', 1), 
('b', 'r', 23), 
('b', 'e', 3))

第二个是dictdicts:

d = {'a' : {'x': 45, 'f' : 4},
     'b' : {'r' : 34, 'e' : 45}}

相同的数据,不同的表示。我现在需要将两者结合起来(并且必须保持元组形式而不是嵌套的 dict 形式),其值为 summed。即

(('a', 'x', 48), 
('a', 'f', 5), 
('b', 'r', 57), 
('b', 'e', 48))

这似乎是一个两步过程(将嵌套的字典转换为元组的元组,然后将每个元组中的相应元组相加)。我正在努力通过第一部分,我缺少两个元组(我也不喜欢我如何硬编码索引):

In [1025]: def f(d):
    for k, v in d.items():
        yield (k, d[k].keys()[0], d[k].values()[0])
   ......:         

In [1026]: for i in f(d):

    print i
   ......:     
('a', 'x', 45)
('b', 'r', 34)

有什么更好的方法?

【问题讨论】:

  • 元组是否有序?
  • 对于周围元组中的各个元组,是的,顺序很重要。至少,在我的代码的其他地方,我已经根据元组中元素的位置进行了硬编码,这很重要,这可能不是最好的方法。

标签: python python-2.7 dictionary casting tuples


【解决方案1】:

您可以在tuple() 中使用生成器表达式,方法是遍历您的元组并将第三项与其在字典中的相对值相加:

>>> tuple((i, j, k + d.get(i, {}).get(j, 0)) for i, j, k in t)
(('a', 'x', 48),
 ('a', 'f', 5),
 ('b', 'r', 57),
 ('b', 'e', 48))

请注意,使用dict.get() 方法的优点是,如果字典中不存在该键,它会返回 0。

请注意,如果拥有一个元组列表或元组的元组对您没有任何影响,您可以使用列表推导式而不是生成器表达式。因为列表解析在运行时方面更加优化,因为它不需要在生成器函数中调用额外的方法,例如 next() 来检索项目。

【讨论】:

  • 想知道您为什么改变了原来的列表理解方法的答案?
  • @Pyderman 因为你想要元组的元组。如果它对您没有任何影响,事实上列表理解方法更优化,因为它不需要在生成器函数中调用额外的方法,如 next() 来检索项目。跨度>
  • 我明白了,是的,这是需要的元组。我熟悉避免KeyErrord.get() 方法,但我什至没有考虑过(在我的完整数据集中确实有可能丢失键)。谢谢。
  • 而且我从来没有想过将两个dict.get() 调用链接在一起。我最终会遇到多个 for 循环,让我无处可去。
  • @Pyderman 是的,那是因为get 返回了该项目,您可以调用返回对象的另一个方法,这就是为什么我使用空字典作为第一个get() 的默认对象。如果第一次获取返回无,它会保留引发属性错误的代码。
【解决方案2】:

您可以使用转换为元组的列表推导,前提是您确定所有元组和字典都包含完全相同的元素(适用于当前示例):

tuple([(x, y, z + d[x][y]) for x, y, z in t ])

正确给出:

(('a', 'x', 48), ('a', 'f', 5), ('b', 'r', 57), ('b', 'e', 48))

【讨论】:

  • 做得很好。是的,我的完整数据集可能有一些不重叠的元素,但你的方法在这里很适合这种简化的情况。谢谢。
猜你喜欢
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 2012-07-15
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多