![](/img/trans.png)
[英]calculate sum of all unique elements in a list based on another list python
[英]Sum of specific elements of a list based on indexes from another list in python
我正在尝试在python音乐片段(来自.xml)中找到具有相同名称的所有音符的持续时间。 我有3个清单:
scales = ['A', 'B', 'C'] #scales names
notesAll = ['B', 'A', 'C', 'A', 'C', 'C'] #note names of the piece
durationsAll = [1, 1.5, 1.5, 1, 1, 2] #duration of each note from notesAll list
我想对所有具有相同名称的笔记从durationsAll列表中总结所有持续时间。 例如,对于notesAll列表中的所有 “ A”(等于scales [0]),我想要类似以下内容:durationsAll [1] + durationsAll [3] = 1.5 +1 = 2.5。 我需要比尝试更好的解决方案:
for sc in scales:
for ntPosition, nt in enumerate(notesAll):
dtOfEach = 0
for dtPosition, dt in enumerate(durationsAll):
if sc == nt:
dtPosotion = ntPosition #I guess here is the problem
dtOfEach = dtOfEach + dt
我想要的结果是: dtOfEach: 2.5 1 4.5
defaultdict在这里很完美(假设音符和音符的持续时间在相应的列表中)
from collections import defaultdict
duration_total = defaultdict(int)
for note in list(zip(notesAll, durationsAll)):
duration_total[note[0]] += note[1]
print(duration_total)
{'B':1,'A':2.5,'C':4.5})
我认为您的问题A:3.5是错字?
编辑
克里斯建议的更新代码:
for note, duration in zip(notesAll, durationsAll):
duration_total[note] += duration
您可以使用索引并按以下步骤进行:
def get_total_duration(note):
return sum(durationsAll[idx] for idx, nt in enumerate(notesAll) if nt == note)
scales = ['A', 'B', 'C'] #scales names
notesAll = ['B', 'A', 'C', 'A', 'C', 'C'] #note names of the piece
durationsAll = [1, 1.5, 1.5, 1, 1, 2]
get_total_duration('A')
2.5
您可以进行间接排序,然后使用groupby
进行分组
from itertools import groupby
scales = ['A', 'B', 'C'] #scales names
notesAll = ['B', 'A', 'C', 'A', 'C', 'C'] #note names of the piece
durationsAll = [1, 1.5, 1.5, 1, 1, 2] #duration of each note from notesAll list
# do indirect sort
idx = sorted(range(len(notesAll)), key=notesAll.__getitem__)
# group and sum
result = {k: sum(map(durationsAll.__getitem__, grp))
for k, grp in groupby(idx, notesAll.__getitem__)}
# {'A': 2.5, 'B': 1, 'C': 4.5}
第一个总和应该是2.5吗? 如果是这样,则此消息末尾的代码应该可以工作。 我认为您基本上是通过使用for循环来实现的,然后进行枚举,但是我不确定第二个枚举是做什么的。
您还可以看到一行:
dtPosotion = ntPosition #I guess here is the problem
dtPosotion是错字吗? 或者您是否正在尝试设置dtPosition = ntPosition。 如果是这样,我认为这是不可能的,因为dtPosition和ntPosition是由您的枚举循环设置的。
scales = ['A', 'B', 'C'] #scales names
notesAll = ['B', 'A', 'C', 'A', 'C', 'C'] #notes names of the piece
durationsAll = [1, 1.5, 1.5, 1, 1, 2] #duration of each note from notesAll list
sums = [0,0,0]
for s in scales:
print "Scale letter:" + str(s)
for i,j in enumerate(notesAll):
if j == s:
sums[scales.index(s)] +=durationsAll[i]
print sums
可以通过列表理解来实现,利用布尔值的行为类似于整数的想法
In [3]: S = ['A', 'B', 'C'] #scales names
...: N = ['B', 'A', 'C', 'A', 'C', 'C'] #note names of the piece
...: D = [1, 1.5, 1.5, 1, 1, 2] #duration of each note from notesAll list
In [4]: [sum(match*d for match, d in zip((n==s for n in N), D)) for s in S]
Out[4]: [2.5, 1.0, 4.5]
如果您需要字典
In [5]: {s:sum(match*d for match, d in zip((n==s for n in N), D)) for s in S}
Out[5]: {'A': 2.5, 'B': 1.0, 'C': 4.5}
或者,避免一个循环并且不导入collections
In [6]: r = {}
In [7]: for n, d in zip(N, D): r[n] = r.get(n, 0) + d
In [8]: r
Out[8]: {'A': 2.5, 'B': 1, 'C': 4.5}
在这里我们不通过索引而是通过使用字典.get(key, default)
方法访问字典中的数据,从而可以正确初始化我们的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.