基于python中另一个列表的索引的列表的特定元素的总和

时间:2017-12-08 08:52:23

标签: python list for-loop indexing sum

我试图在python中找到音乐片段(来自.xml)中具有相同名称的所有音符的持续时间。我有3个列表:

i

我想将durationsAll列表中的所有持续时间与所有具有相同名称的音符相加。例如对于所有来自notesAll列表的' A等于scale [0],我想要类似于:durationsAll [1] + durationsAll [3] = 1.5 + 1 = 2.5。我需要一个比我的尝试更好的解决方案:

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

我想要的结果是: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

5 个答案:

答案 0 :(得分:1)

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在你的问题中是一个错字?


修改

使用Chris的建议更新了代码:

for note, duration in zip(notesAll, durationsAll):
    duration_total[note] += duration

答案 1 :(得分:0)

您可以使用索引并按以下方式继续:

c = Clock()

assert(c.minutes == 0 and c.hours == 0)

for i in range(24):
    assert(c.hours == i)
    for j in range(60):
        assert(c.hours == i and c.minutes == j)
        c.tic()

assert(c.minutes == 0 and c.hours == 0)

输出:

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 :(得分:0)

您可以进行间接排序,然后使用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}

答案 3 :(得分:0)

第一笔金额应该是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

答案 4 :(得分:0)

可以通过列表理解来完成,利用布尔表现得像整数的想法

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)方法,可以正确初始化我们的值。