2012-10-27 167 views
3

第一次發佈在這裏,所以我希望我不會重複任何問題(我檢查,雖然)。從嵌套列表中刪除項目(子列表)根據其元素比較

這裏的交易:

我有一個列表,包含4級元素的子列表,例如[[10,1,3,6],[22,3,5,7],[2,1,4,7],[44,3,1,0]]

我想要做的是:

1)取出具有第四子元素等於零例如[44,3,1,0](容易的部分)

2)拆下具有相同的第二元素項的所有元素,只保留具有最大第一個元素的元素,例如[[10,1,3,6],[2,1,4,7]] -> [10,1,3,6]

我一直在嘗試使用嵌套循環和第二個列表來獲取我想要保留的元素,但我似乎無法指定它。

有沒有可以使用的優雅解決方案?

+2

在你的第一種情況下,該列表不具有第四子元素等於0 –

+0

我不知道您的具體方案是什麼,但我有一種感覺['itertools'](http://docs.python.org/library/itertools.html)會有所幫助。 –

+0

哎呀,修好了! – Orestis

回答

2

如果listA是您的原始列表,並且listB是您的新列表,那麼似乎可以通過遍歷listA來檢查部分(2),檢查當前元素(嵌套列表)是否包含重複的第二個元素,以及if它會比較第一個元素來查看哪個嵌套列表保留在listB中。因此,在僞代碼中:

sizeOfListA = # whatever the original size is 
sizeOfListB = 0 

for i in (sizeOfListA): 
    for j in (sizeOfListB): 
    if listA[i][1] == listB[j][1]: # check if second element is a duplicate 
     if listA[i][0] > listB[j][0]: # check which has the bigger first element 
     listB[j] = listA[i] 
    else: # if second element is unique, append nested list and increment size 
     listB.append(listA[i]) 
     sizeOfListB += 1 

這僅適用於第(2)部分。像Burhan的評論一樣,我確信有一種更優雅的方式可以做到這一點,但我認爲這可以完成工作。另外,這個問題並沒有說明當第一個元素是平等的時候會發生什麼,所以這也需要考慮。

2

你可以使用itertools.groupby

from itertools import groupby 
from operator import itemgetter as ig 

data = [[10,1,3,6],[22,3,5,7],[2,1,4,7],[44,3,1,0]] 

# filter and sort by main key 
valid_sorted = sorted((el for el in data if el[3] != 0), key=ig(1)) 
# ensure identical keys have highest first element first 
valid_sorted.sort(key=ig(0), reverse=True) 
# group by second element 
grouped = groupby(valid_sorted, ig(1)) 
# take first element for each key 
selected = [next(item) for group, item in grouped] 
print selected 
# [[22, 3, 5, 7], [10, 1, 3, 6]] 

或使用dict

d = {} 
for el in valid_sorted: # doesn't need to be sorted - just excluding 4th == 0 
    d[el[1]] = max(d.get(el[1], []), el) 
print d.values() 
# [[10, 1, 3, 6], [22, 3, 5, 7]] 
+0

現在我正在重新訪問我的代碼...我們需要排序嗎?是不是它的結果由以下種類取消? – Orestis

+0

沒有「以下排序」 - 你能解釋一下嗎? –

+0

那麼,valid_sorted是通過按照指定鍵對「數據」列表中沒有0作爲第四個數字的元素進行排序來構造的。根據不同的關鍵,​​按照相反的順序完成下一個分類。我必須缺少一些東西,但是我們不是按照不同的關鍵字排序已經排序的(在前一步)列表嗎?在我看來,如果在排序語句中使用key = ig(0),reverse = True,並且完全跳過排序語句,那麼結果會相同。我可能是錯的,這種排序可能會在第二級進行排序。 – Orestis

1

如果你不關心最終名單的排序,你可以通過第二個項目進行排序,並使用發生器找到第一個的最大值:

l = [[10,1,3,6],[22,3,5,7],[2,1,4,7],[44,3,1,0]] 

remove_zeros_in_last = filter(lambda x: x[3] != 0, l) 

ordered_by_2nd = sorted(remove_zeros_in_last, key=lambda x: x[1]) 

def group_equal_2nd_by_largest_first(ll): 
    maxel = None 
    for el in ll: 
     if maxel is None: 
      maxel = el # Start accumulating maximum 
     elif el[1] != maxel[1]: 
      yield maxel 
      maxel = el 
     elif el[0] > maxel[0]: 
      maxel = el # New maximum 
    if maxel is not None: 
     yield maxel  # Don't forget the last item! 

print list(group_equal_2nd_by_largest_first(ordered_by_2nd)) 

# gives [[10, 1, 3, 6], [22, 3, 5, 7]] 
1

這是用於第二部分:

from itertools import product 

lis = [[10, 1, 3, 6], [22, 3, 5, 7], [2, 1, 4, 7]] 
lis = set(map(tuple, lis)) #create a set of items of lis 
removed = set()    #it will store the items to be removed 

for x, y in product(lis, repeat=2): 
    if x != y: 
     if x[1] == y[1]: 
      removed.add(y if x[0] > y[0] else x) 

print "removed-->",removed 

print lis-removed  #final answer 

輸出:

removed--> set([(2, 1, 4, 7)]) 
set([(22, 3, 5, 7), (10, 1, 3, 6)])