2014-02-07 2 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']] 

Я новичок в python. Это мой первый проект. Может ли кто-нибудь предложить мне хороший метод? возможно, подходящее понимание списка? Или краткое объяснение шагов, которым я должен следовать.

+0

Все реляционные обои того же размера? – Hyperboreus

+0

На самом деле xlist является подсписком большого списка. biglist разделяется на подэлементы равного размера. xlist - один из них. Таким образом, xlist имеет подсети с равным размером. Infact, мне нужно применить один и тот же процесс ко всем другим подспискам большого списка. – Manoj

+1

Это пахнет плохим выбором структуры данных. У вас есть контроль над входом? Скорее всего, лучше изменить, как данные изначально хранятся, а не пытаться разобрать ваш вывод так всесторонне, чтобы узнать, сколько уникальных значений находится в подэлементе 2 каждого элемента каждого списка! –

ответ

2

Pure 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 найдены с использованием сложного выражения генератора, которое должно уменьшить потребность в ОЗУ.

Вывод аналогичным образом сохраняется в количестве выходных файлов, если необходимо, с использованием другого выражения генератора для повторного считывания входного файла и ввода записей ввода в соответствующий выходной файл.

Данные должны пропускаться с небольшим общим объемом использования ОЗУ.

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 - списки списков с разными размерами подписок. Если я хочу применить описанную выше процедуру ко всем другим xlists и хочу сделать это параллельно (так как у меня есть функциональная программа), как это расширить? – 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

Благодарим вас за ответ. Это были бы большие данные. (100 ГБ файлов журнала). Я попробую ваш метод. – Manoj

Смежные вопросы