2014-12-02 3 views
0

У меня есть немного обманщик мозга, приведенные данные, как это:Расширенный группировка в Python

data = [('topic1', (['apples', 'oranges'], 0.14975108213820515)), 
     ('topic2', (['oranges', 'raisins'], 0.14975108213820515)), 
     ('topic3', (['grapes', 'raisins'], 0.14975108213820515)), 
     ('topic4', (['trees', 'flowers'], 0.14975108213820515))] 

Я хочу соединить темы, основанные на, если хотя бы один из текстов в массиве (в 1-ом элементе второго элемента кортежа) является общим. Таким образом, в приведенном выше примере:

topic1 is connected to topic2 
topic2 is connected to topic1 and topic3 
topic3 is connected to topic2 
topic4 is unconnected 

В идеале, мой выход будет выглядеть так:

output = [(topic1,topic2), 
     (topic1,topic2, topic3), 
     (topic3, topic2), 
     (topic4)] 

Итак, учитывая вход как data, как я мог бы получить выход как output. Я думаю, что itertools может быть каким-то образом вовлечен, но я действительно застрял в этом.

+0

Тема 2 имеет общие элементы с Topic1 и Topic3, но Topic1 и Topic3 ​​не имеют и связаны только из-за Topic2. Это имеет значение? – MeetTitan

ответ

2

Эффективным способом является использование set.

>>> set1= set(['apples', 'oranges']) 
>>> set2= set(['oranges', 'raisins']) 
>>> print len(set1.intersection(set2)) 
1 

Так, в основном:

  • создать набор для текста
  • каждой теме для каждой темы, перебирать друг друга тему и проверить len пересечения их текстов устанавливает

topic_text_sets= {topic:set(text) for topic,(text,_) in data} 
topic_related= {} 
for topic1, text1 in topic_text_sets.iteritems(): 
    related= [topic2 for topic2, text2 in topic_text_sets.iteritems() if topic1!=topic2 and len(text1.intersection(text2))>0] 
    print related 

topic1 ['topic2'] 
topic3 ['topic2'] 
topic2 ['topic1', 'topic3'] 
topic4 [] 
0

Разбить его на подзадачи.

Во-первых, вам нужно получить все тексты, возможно, используя понимание списка (или установить понимание, чтобы избежать дубликатов). Затем вам нужно пройти через это, и для каждого текста найдите каждый фрагмент в data, который имеет его как часть этого. Вам не нужно будет использовать itertools - это, вероятно, будет более сложным.

2

Вы бы создать словарь со списками, чтобы захватить соединение:

connections = {} 
for topic, (conns, some_number) in data: 
    for conn in conns: 
     connections.setdefault(conn, set()).add(topic) 

Это отображает значения для подключения к наборам тема.

Теперь вы можете найти обратные соединения; просто получить объединение всех множеств значений соединения, если порядок не имеет значения:

output = [tuple(set().union(*(connections[c] for c in conns))) 
      for topic, (conns, some_number) in data] 

Демо:

>>> data = [('topic1', (['apples', 'oranges'], 0.14975108213820515)), 
...  ('topic2', (['oranges', 'raisins'], 0.14975108213820515)), 
...  ('topic3', (['grapes', 'raisins'], 0.14975108213820515)), 
...  ('topic4', (['trees', 'flowers'], 0.14975108213820515))] 
>>> connections = {} 
>>> for topic, (conns, some_number) in data: 
...  for conn in conns: 
...   connections.setdefault(conn, set()).add(topic) 
... 
>>> [tuple(set().union(*(connections[c] for c in conns))) 
...    for topic, (conns, some_number) in data] 
[('topic1', 'topic2'), ('topic1', 'topic3', 'topic2'), ('topic3', 'topic2'), ('topic4',)] 
>>> from pprint import pprint 
>>> pprint(_) 
[('topic1', 'topic2'), 
('topic1', 'topic3', 'topic2'), 
('topic3', 'topic2'), 
('topic4',)] 

topic в противном случае перейти к фронту, удалив его из набора первой:

output = [(topic,) + tuple(set().union(*(connections[c] for c in conns)) - {topic}) 
      for topic, (conns, some_number) in data] 

>>> [(topic,) + tuple(set().union(*(connections[c] for c in conns)) - {topic}) 
...    for topic, (conns, some_number) in data] 
[('topic1', 'topic2'), ('topic2', 'topic1', 'topic3'), ('topic3', 'topic2'), ('topic4',)] 
>>> pprint(_) 
[('topic1', 'topic2'), 
('topic2', 'topic1', 'topic3'), 
('topic3', 'topic2'), 
('topic4',)] 
1

простой с двумя для цикла:

>>> for i in range(len(data)): 
...  x = set(data[i][1][0]) 
...  for j in range(len(data)): 
...   if len(x & set(data[j][1][0]))>=1: 
...    print data[j][0],    # for python 3 use print() 
...  print 
... 
topic1 topic2 
topic1 topic2 topic3 
topic2 topic3 
topic4 
Смежные вопросы