Условное, посрочное добавление срезов подсписка - PullRequest
0 голосов
/ 02 июля 2019

У меня есть список списков:

ls = [['01',2,3,4], ['02',5,2,4], ['03',2,6,4], ['01',1,3,4]]

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

Таким образом, результат должен выглядеть следующим образом:

result = [['01',3,6,8], ['02',5,2,4], ['03',2,6,4]]
# the first and last original sublists were "combined"

Я попробовал этот код:

ls=[['01',2,3,4],['02',5,2,4],['03',2,6,4],['01',1,3,4]]
totals = {}
for key, value1,value2,value3 in ls:
    totals[key] = totals.get(key, 0) + value1
    totals[key] = totals.get(key, 0) + value2
    totals[key] = totals.get(key, 0) + value3

print(totals)

, но это не моя цель:

{'01': 17, '02': 11, '03': 12}

Ответы [ 4 ]

0 голосов
/ 02 июля 2019

Может быть, что-то более элегантное и использует groupby из itertools:

from itertools import groupby
from operator import itemgetter


ls = [['01', 2, 3, 4], ['02', 5, 2, 4], ['03', 2, 6, 4], ['01', 1, 3, 4]]

res = []
for k, group in groupby(sorted(ls), itemgetter(0)):
  group = [sub[1:] for sub in group]
  res.append([k] + [sum(x) for x in zip(*group)])

print(res)  # -> [['01', 3, 6, 8], ['02', 5, 2, 4], ['03', 2, 6, 4]]

Обратите внимание, что приведенное выше решение отсортирует исходный список ls!

0 голосов
/ 02 июля 2019

Вы можете использовать setdefault вместе с некоторым индексированием для получения желаемых результатов.

ls=[['01',2,3,4],['02',5,2,4],['03',2,6,4],['01',1,3,4]]
totals = {}
for element in ls:
    key ,array = element[0],element[1:]
    for index in range(len(array)):
        totals.setdefault(key,[0]*len(array))[index] += array[index]    
result = []
for key,value in totals.items():
    result.append([key] + value)
print(result)

# you can sort the result to get exactly as you wanted
# you dont need this step if the dictionary is already sorted like in python3
result.sort(key=lambda x:x[0])

print(result)

Редактировать, чтобы обрабатывать случай, когда символы приходят и первый символ выбирается

ls=[['01',2,'a',4],['02',5,2,4],['03',2,3,4],['01',1,'asd',4]]
totals = {}
for element in ls:
    key ,array = element[0],element[1:]
    for index in range(len(array)):
        if key not in totals:
            totals.setdefault(key,array)    
        elif (type(totals[key][index]) == "int") and type(array[index] == "int"):    
            totals[key][index] += array[index]    
result = []
for key,value in totals.items():
    result.append([key] + value)
print(result)

# you can sort the result to get exactly as you wanted
# you dont need this step if the dictionary is already sorted like in python3
result.sort(key=lambda x:x[0])

print(result)

ВЫХОД

В питоне 2

[['02', 5, 2, 4], ['03', 2, 6, 4], ['01', 3, 6, 8]]
[['01', 3, 6, 8], ['02', 5, 2, 4], ['03', 2, 6, 4]]

В питоне 3

[['01', 3, 6, 8], ['02', 5, 2, 4], ['03', 2, 6, 4]]
[['01', 3, 6, 8], ['02', 5, 2, 4], ['03', 2, 6, 4]]
0 голосов
/ 02 июля 2019

Если я получу ваш вопрос, вы по существу пытаетесь создать группу к сумме массива. Лично я бы сделал это:

sum_dictionary = {}

for ls in your_list:
    key = ls[0]
    vals = ls[1:]
    if key not in sum_dictionary:
        sum_dictionary[key] = [vals]
    else:
        sum_dictionary[key].append(vals)

for k, v in sum_dictionary.items():
    sum_dictionary[k] = list(map(sum, zip(*v)))
0 голосов
/ 02 июля 2019

Небольшая поправка к вашему коду, я инициализировал значения [0, 0, 0] при появлении нового «ключа».

ls = [['01', 2, 3, 4],['02', 5, 2, 4],['03', 2, 6, 4],['01', 1, 3, 4]]
totals = {}
for key, value1, value2, value3 in ls:
    if key not in totals.keys():
        totals[key] = [0, 0, 0]
    totals[key][0] += value1
    totals[key][1] += value2
    totals[key][2] += value3

totals = [[k] + v for k, v in totals.items()]
print(totals)

# Output:
# [['01', 3, 6, 8], ['02', 5, 2, 4], ['03', 2, 6, 4]]

Первая проблема вашего кода заключается в том, что totals.get(key, 0) даст вам 0 не наше желаемое начальное значение [0, 0, 0], когда у вас будет новый ключ.

Во-вторых, вы суммируете все значения списка в цикле for вместо того, чтобы суммировать список поэлементно. Следовательно, вы получаете {'01': 17, '02': 11, '03': 12}


Версия 2 (более общая и обрабатывать не числа)

ls = [['01', 2, 'a', 4],['02', 5, 2, 4],['03', 2, 6, 4],['01', 1, 'ad', 4]]
totals = {}
for x in ls:
    if x[0] not in totals.keys():
        totals[x[0]] = x[1:]
    else:
        for i in range(len(totals[x[0]])):
            if isinstance(x[1 + i], (int, float)):
                totals[x[0]][i] += x[1 + i]

totals = [[k] + v for k, v in totals.items()]
print(totals)

# Output:
# [['01', 3, 'a', 8], ['02', 5, 2, 4], ['03', 2, 6, 4]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...