2014-11-18 2 views
2

У меня есть следующий список списков, который содержит 6 записей:Как группировать список-из-списка дистанцией условия в Python

lol = [['a', 3, 1.01], 
     ['x', 5, 1.00], 
     ['k', 7, 2.02], 
     ['p', 8, 3.00], 
     ['b', 10, 1.09], 
     ['f', 12, 2.03]] 

Каждый подсписок в lol содержит 3 элемента:

['a', 3, 1.01] 
    e1 e2 e3 

Вышеприведенный список уже отсортирован в соответствии с e2 (т. Е. 2-й элемент)

Я бы хотел «скопировать» приведенный выше список примерно следующих шагов:

  1. Выберите наименьшую позицию (по запросу. e2) в lol качестве ключа первого кластера
  2. Присвоить, что в качестве первого члена кластера (словарь списка)
  3. Вычислить текущую e3 разницы в следующем списке с первым членом существующих кластеров.
  4. Если разница меньше порога, назначьте этот список как член соответствующего кластера Иначе создайте новый кластер с текущим списком в качестве нового ключа.
  5. Повторите остальные до конца

Окончательный результат будет выглядеть следующим образом, с порогом < = 0,1.

dol = {'a':['a', 'x', 'b'], 
     'k':['k', 'f'], 
     'p':['p']} 

Я застрял с этим, что правильный способ сделать это:

import json 
from collections import defaultdict 

thres = 0.1 
tmp_e3 = 0 
tmp_e1 = "-" 

lol = [['a', 3, 1.01], ['x', 5, 1.00], ['k', 7, 2.02], 
     ['p', 8, 3.00], ['b', 10, 1.09], ['f', 12, 2.03]] 

dol = defaultdict(list) 
for thelist in lol: 
    e1, e2, e3 = thelist 

    if tmp_e1 == "-": 
     tmp_e1 = e1 
    else: 
     diff = abs(tmp_e3 - e3) 
     if diff > thres: 
      tmp_e1 = e1 

    dol[tmp_e1].append(e1) 
    tmp_e1 = e1 
    tmp_e3 = e3 

print json.dumps(dol, indent=4) 
+0

Что такое 'print json.dumps (dol, indent = 4)' дает вам? – Yax

+0

@Yax: '{'a': ['a', 'x'], 'b': ['b'], 'f': ['f'], 'k': ['k'], 'p': ['p']} ' – pdubois

+0

Прости, я вышел, чтобы помолиться. Вы подумаете об этом, выполнив свой код. Теперь включите 'print diff> thress, thelist' в свой' else' оператор, чтобы увидеть подсказку, которую он дает. – Yax

ответ

2

Я бы сначала убедиться LOL сортируется по второму элементу, затем итерацию по поддержанию в списке только то, что в не в преддверии от первого элемента:

import json 

thres = 0.1 
tmp_e3 = 0 
tmp_e1 = "-" 

lol = [['a', 3, 1.01], ['x',5, 1.00],['k',7, 2.02], 
     ['p',8, 3.00], ['b', 10, 1.09], ['f', 12, 2.03]] 

# ensure lol is sorted 
lol.sort(key = (lambda x: x[1])) 
dol = {} 

while len(lol) > 0: 
    x = lol.pop(0) 
    lol2 = [] 
    dol[x[0]] = [ x[0] ] 
    for i in lol: 
     if abs(i[2] - x[2]) < thres: 
      dol[x[0]].append(i[0]) 
     else: 
      lol2.append(i) 
    lol = lol2 

print json.dumps(dol, indent=4) 

Результат:

{ 
    "a": [ 
     "a", 
     "x", 
     "b" 
    ], 
    "p": [ 
     "p" 
    ], 
    "k": [ 
     "k", 
     "f" 
    ] 
} 
+1

+1 Простая и правильная точка! – neversaint

0

Взяв e2/e3 в сторону, вот пример черноты.

Первые данные групп генераторов по значению, однако данные необходимо сортировать по значению.

Затем пример использования, сначала необработанный, а затем с данными, отсортированными по значению.

In [32]: def cluster(lol, threshold=0.1): 
    cl, start = None, None 
    for e1, e2, e3 in lol: 
     if cl and abs(start - e3) <= threshold: 
      cl.append(e1) 
     else: 
      if cl: yield cl 
      cl = [e1] 
      start = e3 
      if cl: yield cl 

In [33]: list(cluster(lol)) 
Out[33]: [['a', 'x'], ['k'], ['p'], ['b'], ['f']] 

In [34]: list(cluster(sorted(lol, key = lambda ar:ar[-1]))) 
Out[34]: [['x', 'a', 'b'], ['k', 'f'], ['p']] 
Смежные вопросы