2009-01-03 19 views
32
分組嵌套列表

我有以下數據結構(列表的列表)排序和在Python

[ 
['4', '21', '1', '14', '2008-10-24 15:42:58'], 
['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
['5', '21', '3', '19', '2008-10-24 15:45:45'], 
['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 
] 

我希望能夠

  1. 使用重新排序列表功能以便我可以按列表中的每個項目進行分組。例如,我希望能夠按第二列進行分組(所有21都在一起)

  2. 使用函數僅顯示每個內部列表中的某些值。例如,我想,以減少該列表只包含「2somename」第四屆字段值

所以列表看起來像這樣

[ 
    ['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
    ['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 
] 
+2

輕微點分組,但你也許應該使用的元組內部列表的 – hop 2009-01-04 00:26:30

回答

45

工作對於第一個問題,首先映入你的第4個字段值應該做的是排序列表中第二場:

x = [ 
['4', '21', '1', '14', '2008-10-24 15:42:58'], 
['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
['5', '21', '3', '19', '2008-10-24 15:45:45'], 
['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 
] 

from operator import itemgetter 

x.sort(key=itemgetter(1)) 

然後你可以使用itertools' GROUPBY功能:

from itertools import groupby 
y = groupby(x, itemgetter(1)) 

現在y是一個包含(元素,項目迭代器)元組的迭代器。這是較爲混亂來解釋這些元組比它表明代碼:

for elt, items in groupby(x, itemgetter(1)): 
    print(elt, items) 
    for i in items: 
     print(i) 

它打印:

21 <itertools._grouper object at 0x511a0> 
['4', '21', '1', '14', '2008-10-24 15:42:58'] 
['5', '21', '3', '19', '2008-10-24 15:45:45'] 
['6', '21', '1', '1somename', '2008-10-24 15:45:49'] 
22 <itertools._grouper object at 0x51170> 
['3', '22', '4', '2somename', '2008-10-24 15:22:03'] 
['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 

對於第二部分,你應該使用列表內涵提到已經在這裏:

from pprint import pprint as pp 
pp([y for y in x if y[3] == '2somename']) 

哪打印:

[['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
['7', '22', '3', '2somename', '2008-10-24 15:45:51']] 
+1

我已經添加了列表理解的例子。 – jfs 2009-01-03 18:34:11

3

如果我正確的理解你的問題下面的代碼應該做的工作:

l = [ 
['4', '21', '1', '14', '2008-10-24 15:42:58'], 
['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
['5', '21', '3', '19', '2008-10-24 15:45:45'], 
['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 
] 

def compareField(field): 
    def c(l1,l2): 
     return cmp(l1[field], l2[field]) 
    return c 

# Use compareField(1) as the ordering criterion, i.e. sort only with 
# respect to the 2nd field 
l.sort(compareField(1)) 
for row in l: print row 

print 
# Select only those sublists for which 4th field=='2somename' 
l2somename = [row for row in l if row[3]=='2somename'] 
for row in l2somename: print row 

輸出:

['4', '21', '1', '14', '2008-10-24 15:42:58'] 
['5', '21', '3', '19', '2008-10-24 15:45:45'] 
['6', '21', '1', '1somename', '2008-10-24 15:45:49'] 
['3', '22', '4', '2somename', '2008-10-24 15:22:03'] 
['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 

['3', '22', '4', '2somename', '2008-10-24 15:22:03'] 
['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 
+0

在2.6/3.0中將'cmp'參數排序,因此,最好使用提取排序鍵的'key'參數,否則使用+1。 – 2009-01-03 17:29:18

+0

刪除'cmp =',無論如何應該是第一個參數。順便說一下,我使用的Python 2.6.1和所有工作正常... – 2009-01-03 17:36:49

7

如果你把它分配給VAR 「一」 ...

#1:

a.sort(lambda x,y: cmp(x[1], y[1])) 

#2:

filter(lambda x: x[3]=="2somename", a) 
+0

比itemgetter – 2016-06-30 09:18:09

+0

lambda更簡單和更乾淨的方法爲勝利。我真的很喜歡這個解決方案 – alfredocambera 2016-11-10 19:31:01

2

使用函數重新排序列表,以便我可以按列表中的每個項目進行分組。例如,我希望能夠按第二列進行分組(所有21都在一起)

列表有一個內置的排序方法,您可以提供一個提取排序鍵的函數。

>>> import pprint 
>>> l.sort(key = lambda ll: ll[1]) 
>>> pprint.pprint(l) 
[['4', '21', '1', '14', '2008-10-24 15:42:58'], 
['5', '21', '3', '19', '2008-10-24 15:45:45'], 
['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
['7', '22', '3', '2somename', '2008-10-24 15:45:51']] 

使用僅顯示從每個內部列表中的某些值的函數。例如,我想,以減少該列表只包含「2somename」

這看起來像list comprehensions

>>> [ll[3] for ll in l] 
['14', '2somename', '19', '1somename', '2somename'] 
+0

用`[ll]替換'[ll [3] for l'`如果ll [3] =='2somename']`並修復輸出。 – jfs 2009-01-03 18:39:05

2

如果您要進行大量排序和過濾,您可能會喜歡一些幫助功能。

m = [ 
['4', '21', '1', '14', '2008-10-24 15:42:58'], 
['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
['5', '21', '3', '19', '2008-10-24 15:45:45'], 
['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 
] 

# Sort and filter helpers. 
sort_on = lambda pos:  lambda x: x[pos] 
filter_on = lambda pos,val: lambda l: l[pos] == val 

# Sort by second column 
m = sorted(m, key=sort_on(1)) 

# Filter on 4th column, where value = '2somename' 
m = filter(filter_on(3,'2somename'),m) 
1

看起來很像你試圖使用列表作爲數據庫。

當今Python在覈心發行版中包含sqlite綁定。如果您不需要持久性,那麼創建內存中的sqlite數據庫非常簡單(請參閱How do I create a sqllite3 in-memory database?)。

然後,您可以使用SQL語句來執行所有這些排序和過濾,而無需重新發明輪子。

2

對於部分(2),其中x爲您的數組,我想你想,

[y for y in x if y[3] == '2somename'] 

將返回具有第四值是「2somename」只是你的數據列表的列表...儘管看起來卡米爾正在爲SQL提供最好的建議......

1

你只是在你的結構上創建索引,對不對?

>>> from collections import defaultdict 
>>> def indexOn(things, pos): 
...  inx= defaultdict(list) 
...  for t in things: 
...    inx[t[pos]].append(t) 
...  return inx 
... 
>>> a=[ 
... ['4', '21', '1', '14', '2008-10-24 15:42:58'], 
... ['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
... ['5', '21', '3', '19', '2008-10-24 15:45:45'], 
... ['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
... ['7', '22', '3', '2somename', '2008-10-24 15:45:51'] 
... ] 

這是你的第一個請求,按位置分組1.

>>> import pprint 
>>> pprint.pprint(dict(indexOn(a,1))) 
{'21': [['4', '21', '1', '14', '2008-10-24 15:42:58'], 
     ['5', '21', '3', '19', '2008-10-24 15:45:45'], 
     ['6', '21', '1', '1somename', '2008-10-24 15:45:49']], 
'22': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
     ['7', '22', '3', '2somename', '2008-10-24 15:45:51']]} 

這裏是你的第二個請求,通過位置3.

>>> dict(indexOn(a,3)) 
{'19': [['5', '21', '3', '19', '2008-10-24 15:45:45']], '14': [['4', '21', '1', '14', '2008-10-24 15:42:58']], '2somename': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'], ['7', '22', '3', '2somename', '2008-10-24 15:45:51']], '1somename': [['6', '21', '1', '1somename', '2008-10-24 15:45:49']]} 
>>> pprint.pprint(_) 
{'14': [['4', '21', '1', '14', '2008-10-24 15:42:58']], 
'19': [['5', '21', '3', '19', '2008-10-24 15:45:45']], 
'1somename': [['6', '21', '1', '1somename', '2008-10-24 15:45:49']], 
'2somename': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
       ['7', '22', '3', '2somename', '2008-10-24 15:45:51']]}