Condenseing/converting 使用字典理解的嵌套列表
Condenseing/converting a nested list using dictionary comprehension
所以我的数据结构像这样嵌套列表
data = [['A', '1'], ['B', '2'], ['C', '3'], ['A', '-2'], ['B', '4'], ['C', '1'], ['A', '2'], ['B', '1'], ['C', '-5']]
我正在尝试将其转换成如下所示的输出
{'A': 1, 'C': -1, 'B': 7}
基本上把A、B、C全部加起来,输出成字典。
我写了这段给出正确答案的代码
playerSum = {}
for ele in data:
if ele[0] not in playerSum:
playerSum[ele[0]] = int(ele[1])
else:
playerSum[ele[0]] += int(ele[1])
但是,我正在尝试将上面的代码块转换为字典理解。我主要了解如何去做,但我不明白如何将 += 写成字典理解。任何关于结构的指导都会很棒。
到目前为止我有这个
playerSum = {ele[0]: int(ele[1]) if ele[0] not in playerSum else playerSum[ele[0]] += int(ele[1]) for ele in data}
编辑:所以@achampion 能够解决它。谢谢!
{key: sum(int(v) for k, v in data if k==key) for key in set(k for k, _ in data)}
最好的方法是最明显的方法
from collections import defaultdict
playerSum = defaultdict(int)
for key, value in data:
playerSum[key] += int(value)
不可能使用字典理解,因为你的值会被覆盖,直到理解完成后才会创建字典,所以即使你可以也没有到+=。
按照目前的情况,除非你有 playerSum = {}
某处你的代码会出错并出现 NameError,如果你这样做你只是将名称重新绑定到你的 dict comp 的结果所以 playerSum = {}
基本上什么都不做。
做你想做的唯一方法就是按照你自己的解决方案行事。为了更有效的方法,您可以 解压 子列表并将第二个元素转换为 int,使用 collections.defaultdict
:
对值求和
from collections import defaultdict
d = defaultdict(int)
for a,b in data:
d[a] += int(b)
print(d)
defaultdict(<type 'int'>, {'A': 1, 'C': -1, 'B': 7})
或者使用普通的字典:
d = {}
for a, b in data:
d[a] = d.get(a,0) + int(b)
print(d)
{'A': 1, 'C': -1, 'B': 7}
按照你的要求,我在一次理解中做到了。
dict ([(key, sum(int(elem[1]) for elem in data if elem[0]==key)) for key in [id for id in set([elem[0] for elem in data])] ])
从外到内:
构建一组在列表中使用的 ID。
为每个 ID 列出相关值。
对列表求和。
发出(产生)ID 并作为一对求和。
将这个元组列表变成字典。
测试:
data = [['A', '1'], ['B', '2'], ['C', '3'],
['A', '-2'], ['B', '4'], ['C', '1'],
['A', '2'], ['B', '1'], ['C', '-5']]
playerSum = dict ([(key, sum(int(elem[1]) for elem in data if elem[0]==key))
for key in [id for id in set([elem[0] for elem in data])] ])
print data
print playerSum
结果:
[['A', '1'], ['B', '2'], ['C', '3'], ['A', '-2'], ['B', '4'], ['C', '1'], ['A', '2'], ['B', '1'], ['C', '-5']]
{'A': 1, 'C': -1, 'B': 7}
做为领悟不切实际
作为练习,您可以使用协同程序为您进行计数,但实际上您创建了两次字典:
from collections import defaultdict
def count():
cache = defaultdict(int)
k, v = yield
while True:
cache[k] += v
k, v = yield cache[k]
counter = count() # Create coroutine
next(counter) # Prime coroutine
data = [['A', '1'], ['B', '2'], ['C', '3'], ['A', '-2'], ['B', '4'],
['C', '1'], ['A', '2'], ['B', '1'], ['C', '-5']]
{k: counter.send((k, int(v))) for k, v in data} # Meets the challenge :)
结果:
{'A': 1, 'B': 7, 'C': -1}
或者一个真正丑陋的单行代码,它不需要协程而且不是二次方的(不是理解):
>>> reduce(lambda d, (k,v): d.__setitem__(k, d.get(k,0)+int(v)) or d, data, {}) # Py2.7
{'A': 1, 'B': 7, 'C': -1}
最后是一个非常低效但真实的基于@Prune 的字典理解:
>>> {key: sum(int(v) for k, v in data if k==key) for key in set(k for k, _ in data)}
{'A': 1, 'B': 7, 'C': -1}
所以我的数据结构像这样嵌套列表
data = [['A', '1'], ['B', '2'], ['C', '3'], ['A', '-2'], ['B', '4'], ['C', '1'], ['A', '2'], ['B', '1'], ['C', '-5']]
我正在尝试将其转换成如下所示的输出
{'A': 1, 'C': -1, 'B': 7}
基本上把A、B、C全部加起来,输出成字典。
我写了这段给出正确答案的代码
playerSum = {}
for ele in data:
if ele[0] not in playerSum:
playerSum[ele[0]] = int(ele[1])
else:
playerSum[ele[0]] += int(ele[1])
但是,我正在尝试将上面的代码块转换为字典理解。我主要了解如何去做,但我不明白如何将 += 写成字典理解。任何关于结构的指导都会很棒。
到目前为止我有这个
playerSum = {ele[0]: int(ele[1]) if ele[0] not in playerSum else playerSum[ele[0]] += int(ele[1]) for ele in data}
编辑:所以@achampion 能够解决它。谢谢!
{key: sum(int(v) for k, v in data if k==key) for key in set(k for k, _ in data)}
最好的方法是最明显的方法
from collections import defaultdict
playerSum = defaultdict(int)
for key, value in data:
playerSum[key] += int(value)
不可能使用字典理解,因为你的值会被覆盖,直到理解完成后才会创建字典,所以即使你可以也没有到+=。
按照目前的情况,除非你有 playerSum = {}
某处你的代码会出错并出现 NameError,如果你这样做你只是将名称重新绑定到你的 dict comp 的结果所以 playerSum = {}
基本上什么都不做。
做你想做的唯一方法就是按照你自己的解决方案行事。为了更有效的方法,您可以 解压 子列表并将第二个元素转换为 int,使用 collections.defaultdict
:
from collections import defaultdict
d = defaultdict(int)
for a,b in data:
d[a] += int(b)
print(d)
defaultdict(<type 'int'>, {'A': 1, 'C': -1, 'B': 7})
或者使用普通的字典:
d = {}
for a, b in data:
d[a] = d.get(a,0) + int(b)
print(d)
{'A': 1, 'C': -1, 'B': 7}
按照你的要求,我在一次理解中做到了。
dict ([(key, sum(int(elem[1]) for elem in data if elem[0]==key)) for key in [id for id in set([elem[0] for elem in data])] ])
从外到内:
构建一组在列表中使用的 ID。
为每个 ID 列出相关值。
对列表求和。
发出(产生)ID 并作为一对求和。
将这个元组列表变成字典。
测试:
data = [['A', '1'], ['B', '2'], ['C', '3'],
['A', '-2'], ['B', '4'], ['C', '1'],
['A', '2'], ['B', '1'], ['C', '-5']]
playerSum = dict ([(key, sum(int(elem[1]) for elem in data if elem[0]==key))
for key in [id for id in set([elem[0] for elem in data])] ])
print data
print playerSum
结果:
[['A', '1'], ['B', '2'], ['C', '3'], ['A', '-2'], ['B', '4'], ['C', '1'], ['A', '2'], ['B', '1'], ['C', '-5']]
{'A': 1, 'C': -1, 'B': 7}
做为领悟不切实际
作为练习,您可以使用协同程序为您进行计数,但实际上您创建了两次字典:
from collections import defaultdict
def count():
cache = defaultdict(int)
k, v = yield
while True:
cache[k] += v
k, v = yield cache[k]
counter = count() # Create coroutine
next(counter) # Prime coroutine
data = [['A', '1'], ['B', '2'], ['C', '3'], ['A', '-2'], ['B', '4'],
['C', '1'], ['A', '2'], ['B', '1'], ['C', '-5']]
{k: counter.send((k, int(v))) for k, v in data} # Meets the challenge :)
结果:
{'A': 1, 'B': 7, 'C': -1}
或者一个真正丑陋的单行代码,它不需要协程而且不是二次方的(不是理解):
>>> reduce(lambda d, (k,v): d.__setitem__(k, d.get(k,0)+int(v)) or d, data, {}) # Py2.7
{'A': 1, 'B': 7, 'C': -1}
最后是一个非常低效但真实的基于@Prune 的字典理解:
>>> {key: sum(int(v) for k, v in data if k==key) for key in set(k for k, _ in data)}
{'A': 1, 'B': 7, 'C': -1}