2017-02-20 119 views
2

我有一個list其中包含sorted tuplesbased2nd element元組。提供排名數字包含python排序元組列表

樣品名單如下:

[ ('not', 48), 
('this', 47), 
('which', 45), 
('by', 45), 
('as', 44), 
('are', 42), 
('will', 41), 
('i', 40), 
('but', 38), 
('all', 38), 
('with', 34) ] 

我需要提供rank_number到每個元組如下:

[ ('not', 48, 1), 
('this', 47, 2), 
('which', 45, 3), 
('by', 45, 3), 
('as', 44, 5), 
('are', 42, 6), 
('will', 41, 7), 
('i', 40, 8), 
('but', 38, 9), 
('all', 38, 9), 
('with', 34, 11) ] 

我試着寫for循環和第二個元素對方,但並不在比較在第二元素相同的情況下獲得適當的排名。

,我試過的代碼如下:

sorted_rank_words = [] 
rank_number = 1 
list1 = sorted_words 
count1 = 0 
count2 = 0 

for x in sorted_words: 
    r1 = list1.index(x) 
    list1.pop(r1) 
    for y in list1: 
    if x[1] > y[1]: 
     count1 = count1 + 1 

    elif x[1] == y[1]: 
     count2 = count2 + 1 

    if count1 > 0: 
    sorted_rank_words.append(x+(rank_number,)) 
    rank_number = rank_number + 1 

    elif count2 > 0: 
    sorted_rank_words.append(x+(rank_number,)) 
    rank_number = rank_number + count2 
    count1 = 0 
    count2 = 0 
+0

向我們展示您編寫的代碼! – Elmex80s

+0

@ Elmex80s更新了帖子。請檢查。 –

回答

2

如果你想要一個更新的項目的新列表,那麼你可以做。

rank = 0 
skip = 0 
prev = None 

res = [] 
for word, v in lst: 
    if v == prev: 
     skip += 1 
    else: 
     rank += skip + 1 
     skip = 0 

    res.append((word, v, rank))  
    prev = v 

或者如果你想更新你現有的清單,那麼你可以做。

rank = 0 
skip = 0 
prev = None 

for i, (word, v) in enumerate(lst): 
    if v == prev: 
     skip += 1 
    else: 
     rank += skip + 1 
     skip = 0 

    lst[i] += (rank,) 
    prev = v 

我真的很喜歡使用itertools.groupby麥蒂的原來的答案,並希望使它的工作,因爲這是一個有點清潔,所以我也在這裏加入我的更新版本。

from itertools import groupby 

result = [] 
skip = 0 
for rank, (_, g) in enumerate(groupby(lst, key=lambda xs: xs[1]), 1): 
    count = -1 
    for v in g: 
     count += 1 
     result.append(v + (rank + skip,)) 
    skip += count 
+0

謝謝。它根據需要提供了O/P。我不確定我是否可以使用第二種方法,因爲列表包含元組,所以我無法更新列表。 –

+0

你可以更新列表本身,你不能更新元組。它所做的就是用新的元組替換舊的元組。 –

+0

明白了你的觀點。謝謝! –

1

元組是不可變的那麼做到這一點的最佳方式,通過元組併爲每個元組創建軍銜加入到一個新的循環結束了。

rank = 1 
for tuple in tuples: 
    tuple = tuple + (rank,) 
    rank += 1 

這應該工作,如果我正確地理解問題。您可能需要根據您希望的級別來調整/比較排名。

+0

是的,我知道這一點。在將rank添加到現有的元組後,我創建了一個新列表,但是我的問題是第二個元素相同的地方,它們的排名應該相同。 –

+0

所以,當你開始你的循環嘗試跟蹤第二個元素。如果你現在的一個和前一個一樣,不要增加排名。 – Scragglez

2

試試這個:

result=[] 


tmp=0 
rank=0 
count=1 
for i in tuples: 
    if i[1]==tmp: 
     result.append(i+(rank,)) 
    else: 
     result.append(i + (count,)) 
    tmp=i[1] 
    rank=count 
    count+=1 

print result 

你會得到

[('not', 48, 1), ('this', 47, 2), ('which', 45, 3), ('by', 45, 3), ('as', 44, 5), ('are', 42, 6), ('will', 41, 7), ('i', 40, 8), ('but', 38, 9), ('all', 38, 9), ('with', 34, 11)] 

希望這有助於。

+0

我試過你的解決方案,它給了我第二個元素相同但最後一個元素追加一個額外時間的元素相同的排名。 ('which',45,17), ('by',45,17), ('by',45,18), –

+0

@PrashantVikramSingh它適用於我,我只是更新另一種方式,試試這個。 – McGrady

+0

它的工作,但你可以解釋一下它是如何工作的。我的意思是語法。非常感謝。 –

0

最近,我得到了這個 「短」 的解決方案:

定義base元組

b = [('',10e10)]+base[:] 
r,s =[],[] 
for x in range(len(b)-1): 
    r+=[bool(b[x][1] - b[x+1][1])] 
    s+=[(b[x+1] + (sum(r),))] 

這將做到這一點的陣列,

有趣後,我注意到,需要在第一個「得分」數組上進行2次數學運算: 不同,並且是整數,但是我沒有把它放到一個線性中

1

```

results = [] 
prevcount, prevrank = 0, 1 
for idx, t in enumerate(inputs): 
    # when the current count is similar to the previous one 
    if t[1] == prevcount: 
     # add rank to the tuple and append to the results list 
     results.append(t + (prevrank,)) 
    else: 
     results.append(t + (idx + 1,)) 
    # update rank and count 
    prevrank = idx + 1 
    prevcount = t[1] 

```

注:通過輸入列表迭代。當前計數與前一個計數相似時,我們可以使排序與前一個相同並將其連接到元組;然後,追加到結果列表。否則,排名是輸入列表中元組的位置(從索引1開始)。

+0

感謝您的解決方案! –

+0

歡迎:) –