簡體   English   中英

基於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM