2014-02-07 83 views
0

我有以下列表的列表。Python:通過唯一值分隔列表

xlist =[['instructor','plb','error0992'],['instruction','address','00x0993'],['data','address','017x112']]] 

我想實現在哪裏一步,它需要上面的列表分成多個列表的字符串算法。分離標準是首先選擇最少數量的唯一標記值,並使用唯一標記值將其分開。 (這裏的標記是內部列表的一個元素)。例如,在上面的xlist中,唯一標記的最少數量駐留在第二個索引=>('plb','address','address')中。所以我需要將這個列表分成以下兩個列表。

list1 = [['instruction','address','00x0993'],['data','address','017x112']] 
list2= [['instructor','plb','error0992']] 

我是新來的蟒蛇。這是我的第一個項目。任何人都可以給我一個好方法嗎?也許是一個合適的列表理解?或者我應該遵循的步驟的簡要說明。

+0

是否所有的子列表大小相同? – Hyperboreus

+0

實際上xlist是一個biglist的子列表。 biglist被分成相同大小的子列表。 xlist就是其中之一。所以xlist具有相同大小的子列表。事實上,我需要對biglist的所有其他子列表應用相同的過程。 – Manoj

+1

這種糟糕的數據結構選擇。你有任何控制輸入?改變數據最初的存儲方式可能會更好,而不是試圖如此全面地分析輸出,以便知道每個列表中每個元素的子元素2中有多少個唯一值! –

回答

2

純Python,內存中,解決方案。 (因爲當你有內存時)

要獲得名稱集,我轉置xlist然後形成一組每個轉置的元素,將刪除任何重複。

mintokenset只找到項目數量最少的集合。

minindex查找內部列表mintokenset所對應的列。

名稱列表被初始化爲具有足夠空的內部列表。

for循環採用該信息來適當地拆分內部列表。

>>> from pprint import pprint as pp 
>>> 
>>> xlist =[['instructor','plb','error0992'],['instruction','address','00x0993'],['data','address','017x112']] 
>>> sets = [set(transposedcolumn) for transposedcolumn in zip(*xlist)] 
>>> pp(sets) 
[{'instructor', 'data', 'instruction'}, 
{'plb', 'address'}, 
{'00x0993', '017x112', 'error0992'}] 
>>> mintokenset = min(sets, key=lambda x:len(x)) 
>>> mintokenset 
{'plb', 'address'} 
>>> minindex = sets.index(mintokenset) 
>>> minindex 
1 
>>> mintokens = sorted(mintokenset) 
>>> mintokens 
['address', 'plb'] 
>>> lists = [[] for _ in mintokenset] 
>>> lists 
[[], []] 
>>> for innerlist in xlist: 
    lists[mintokens.index(innerlist[minindex])].append(innerlist) 


>>> pp(lists) 
[[['instruction', 'address', '00x0993'], ['data', 'address', '017x112']], 
[['instructor', 'plb', 'error0992']]] 
>>> 

從上述塗鴉繼,大數據,假設它被存儲在一個文件中(每行一個內部列表,逗號隔開)。該文件可以讀取一次,mintokenset和minindex使用一個複雜的生成器表達式來發現,該表達式可以降低RAM的要求。

使用另一個生成器表達式第二次讀取輸入文件並將輸入記錄切換到相應的輸出文件時,輸出類似地存儲在儘可能多的輸出文件中。

數據應該流經很少的整體RAM使用量。

from pprint import pprint as pp 

def splitlists(logname): 
    with open(logname) as logf: 
     #sets = [set(transposedcolumn) for transposedcolumn in zip(*(line.strip().split(',') for line in logf))] 
     mintokenset, minindex = \ 
      min(((set(transposedcolumn), i) 
       for i, transposedcolumn in 
       enumerate(zip(*(line.strip().split(',') for line in logf)))), 
       key=lambda x:len(x[0])) 
    mintokens = sorted(mintokenset) 
    lists = [open(r'C:\Users\Me\Code\splitlists%03i.dat' % i, 'w') for i in range(len(mintokenset))] 
    with open(logname) as logf: 
     for innerlist in (line.strip().split(',') for line in logf): 
       lists[mintokens.index(innerlist[minindex])].write(','.join(innerlist) + '\n') 
    for filehandle in lists: 
     filehandle.close() 

if __name__ == '__main__': 
    # File splitlists.log has the following input 
    '''\ 
instructor,plb,error0992 
instruction,address,00x0993 
data,address,017x112''' 

    logname = 'splitlists.log' 
    splitlists(logname) 

    # Creates the following two output files: 
    # splitlists000.dat 
    '''\ 
instruction,address,00x0993 
data,address,017x112''' 
    # splitlists001.dat 
    '''\ 
instructor,plb,error0992''' 
+0

太棒了!我想我可以忍受這一點。 但是我有另外一個問題。 biglist = [xlist1,xlist2,xlist3 ..]其中xlist 是具有不同子列表大小的列表列表。如果我想將上述過程應用於所有其他x列表並希望並行執行(因爲我有一個功能程序)如何擴展它? – Manoj

+0

再次感謝處理大日誌文件的建議。我以前想過把日誌文件分成幾塊,並行處理。 – Manoj

1

既然你提到它會是一個很大的數據集(有多大?),我認爲pandas可能是最好的方法。

In [1]: 
import numpy as np 
import pandas as pd 

In [4]: 
xlist =[['instructor','plb','error0992'],['instruction','address','00x0993'],['data','address','017x112']] 
df=pd.DataFrame(xlist, columns=['c1','c2','c3']) 

In [6]: 
set(df['c2']) 

Out[6]: 
{'address', 'plb'} 

In [11]: 
print df[df['c2']=='address'] 

      c1  c2  c3 
1 instruction address 00x0993 
2   data address 017x112 

In [12]: 
print df[df['c2']=='plb'] 

      c1 c2   c3 
0 instructor plb error0992 
+0

謝謝你的回答。這將是大數據。 (100GB的日誌文件)。我會嘗試你的方法。 – Manoj