2014-02-07 75 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