сравнить первый индекс подсписков (в списке списков), а затем преобразовать его в набор и обратно - PullRequest
0 голосов
/ 04 мая 2018

У меня есть список списков. Я хочу собрать все подсписки с одним и тем же первым элементом, объединить их элементы и удалить дубликаты. Я уже близко, но мое текущее решение умирает из-за ошибки индекса.

Токовый выход:

[[1, 2, 3, 7, 8, 9], [5, 5, 8], [2, 2, 0, 2, 3, 4, 5, 6]]

Правильный вывод:

[[1, 2, 3, 7, 8, 9], [4, 5, 6, 3, 2], [5, 5, 8], [2, 2, 0]] (not necessarily in that order)

Код:

listoflist = [[1,2,3,1],[4,5,6],[1,7,8],[4,3,2],[5,5,8],[2,2,0],[1,9,9]]

try: #(try and except is to deal with when lists are removed)
    for i in range(len(listoflist)): #iterating forwards
        x = listoflist[i][0] #indexing through sublists and setting the first value
        for j in range(len(listoflist)-1,0,-1): #iterating backwards
            if x == listoflist[j][0] and listoflist[i] != listoflist[j]: #comparing
                listoflist[i].extend(listoflist[j]) #combining lists and removing the old list
                listoflist.remove(listoflist[j]) 
                new = set(listoflist[i]) #conversion to set and back to list
                listoflist[i] = list()
                for obj in new:
                    listoflist[i].append(obj)
                    print listoflist[i]
    print listoflist


except IndexError:
    print listoflist

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

АНАЛИЗ

Ваша основная проблема заключается в том, что вы нарушаете базовую практику: не изменяйте итерацию, пока вы ее повторяете. Ваш внешний цикл запускает i через значения 0-5. Однако к тому времени, как вы доберетесь до 4, у вас больше не будет пункта № 4 в списке. Я сделал несколько простых трассировок вашего кода, включая лучшее сообщение об ошибке:

except IndexError:
    print "ERROR", i, j, listoflist

Выход:

ERROR 4 1 [[1, 2, 3, 1, 1, 9, 9, 1, 7, 8], [4, 5, 6, 4, 3, 2], [5, 5, 8], [2, 2, 0]]

РЕМОНТ

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

listoflist = [[1,2,3,1],[4,5,6],[1,7,8],[4,3,2],[5,5,8],[2,2,0],[1,9,9]]
result = []

try:
    for i in range(len(listoflist)):
        x = listoflist[i][0]
        if x < 0:                       # Skip any sub-list already used
            continue

        gather = listoflist[i][:]       # Copy list for processing
        for j in range(len(listoflist)-1,0,-1):
            if x == listoflist[j][0] and i != j:
                gather.extend(listoflist[j])
                listoflist[j][0] = -j   # Uniquely mark this as not in use.
                print i, j, gather

        result.append(list(set(gather)))
        print i, result

    print result


except IndexError:
    print "ERROR", i, j, listoflist

Да, это все еще намного дольше, чем нужно; если вы действительно хотите копаться в Python, вы можете сгруппировать списки по первому элементу и выполнить всю обработку в одну длинную строку. Я пытался сделать это более доступным для вас.

0 голосов
/ 04 мая 2018

Вот мое решение. Я пошел для построения dict{} на основе первого элемента в списке в качестве ключа и объединения списков на основе этого.

listoflist = [[1,2,3,1],[4,5,6],[1,7,8],[4,3,2],[5,5,8],[2,2,0],[1,9,9]]
temp_dict = {}
result_list = []

# build a dict{int:list[]} based on first elem of list
for ll in listoflist:
  if ll[0] not in temp_dict:
    temp_dict[ll[0]]=ll
  else:
    for x in ll:
      temp_dict[ll[0]].append(x)
# now build a list of list with our dict
for key, values in temp_dict.items():
  temp_list = []
  temp_list.append(key)
  for x in values:
    if x not in temp_list:
      temp_list.append(x)
  result_list.append(temp_list)

print(result_list)

Выход:

[[1, 2, 3, 7, 8, 9], [4, 5, 6, 3, 2], [5, 8], [2, 0]]
...