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

基于python中另一个列表的索引的列表特定元素的总和,python,list,for-loop,indexing,sum,Python,List,For Loop,Indexing,Sum,我试图在python中查找音乐片段(from.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 我想对durationsA

我试图在python中查找音乐片段(from.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',它等于刻度[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.514.5

defaultdict在这里是完美的(当然,假设音符和音符的持续时间在相应的列表中)

{'B':1,'A':2.5,'C':4.5})

我认为你问题中的A:3.5是一个打字错误


编辑

使用Chris的建议更新代码:

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')
输出:
您可以进行间接排序,然后使用
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 [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)
方法,该方法可以正确初始化我们的值。

1.5+1=3.5
当然,这是一个打字错误
对于note,duration in zip(notesAll,durationsAll):duration\u total[note]+=持续时间
非常感谢您的帮助,尽管我想按音符在音阶中出现的顺序打印持续时间。(当然3.5是错的,实际上是微算的)非常感谢你,这正是我想要的,你帮了我很多!(我试图设置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}
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}