python #list #for-loop #if-statement
#python #Список #for-цикл #if-оператор
Вопрос:
У меня есть вопрос (python) относительно добавления значений в список, если они имеют один и тот же ключ в первом списке. Так, например, мы имеем:
lst1 = [A, A, B, A, C, D]
lst2 = [1, 2, 3, 4, 5, 6]
Что я хотел бы знать, так это то, как я могу добавить числа в lst2, если строки в lst1 являются нормальными. Таким образом, конечный результат будет:
new_lst1 = [A, B, A, C, D]
new_lst2 = [3, 3, 4, 5, 6]
где
new_lst2[0] = 1 2
Таким образом, значения добавляются только тогда, когда они находятся рядом друг с другом.
Чтобы сделать это более сложным, это также должно быть возможно, если у нас есть этот пример:
lst3 = [A, A, A, B, B, A, A]
lst4 = [1, 2, 3, 4, 5, 6, 7]
для чего результат должен быть:
new_lst3 = [A, B, A]
new_lst4 = [6, 9, 13]
где
new_lst4[0] = 1 2 3
, new_lst4[1] = 4 5
, и new_lst4[2] = 6 7
.
Заранее спасибо!
для справки: я написал код, который выполняет поиск в голландских онлайн-моделях метро и возвращает данные метро определенного местоположения ввода.
Данные состоят из слоев:
Layer1, Имя:
«BXz1», top_layer, bottom_layer, слой транзитивности2, Имя: «BXz2», top_layer, bottom_layer, слой транзитивности3, Имя: «KRz1», top_layer, bottom_layer, transitivity
и т.д..
BXz1 и BXz2 — это один и тот же основной уровень, но разные подуровни. С точки зрения транзитивности я хотел бы объединить их, если они находятся рядом друг с другом. таким образом, я бы получил:
Layer1 2, Имя: BX, top_layer1, bottom_layer2, комбинированный слой транзитивности 3, Имя: «KRz1», top_layer, bottom_layer, транзитивность
Комментарии:
1. Какой язык? Добавьте соответствующие теги к вашему вопросу. Также, пожалуйста, покажите, что вы пробовали до сих пор, и опишите, где вы застряли; StackOverflow — это не сервис для написания кода.
2. спасибо за предупреждение, на python (отредактировал вопрос для ясности)
3. Зачем вам это нужно? Похоже, у вас странный формат данных, что делает этот первый список?
4. смотрите добавленное редактирование
Ответ №1:
Если вам не разрешено использовать библиотеки, вы можете сделать это с помощью простого цикла, используя zip() для сопряжения ключей и значений.
lst3 = ["A", "A", "A", "B", "B", "A", "A"]
lst4 = [1, 2, 3, 4, 5, 6, 7]
new_lst3,new_lst4 = lst3[:1],[0] # initialize with first key
for k,n in zip(lst3,lst4): # pair up keys and numbers
if new_lst3[-1] != k: # add new items if key changed
new_lst3.append(k)
new_lst4.append(0)
new_lst4[-1] = n # tally for current key
print(new_lst3) # ['A', 'B', 'A']
print(new_lst4) # [6, 9, 13]
Если у вас все в порядке с библиотеками, groupby из itertools в сочетании с итератором по ключам позволит вам выразить это более кратко:
from itertools import groupby
tally = ((k,sum(n)) for i3 in [iter(lst3)]
for k,n in groupby(lst4,lambda _:next(i3)))
new_lst3,new_lst4 = map(list,zip(*tally))
Комментарии:
1. Я должен признать, что ваша реализация groupby очень умна, хотя и трудна для чтения. Это также быстрее, чем у меня, примерно на 25% (как показано в списках с миллионом элементов). Ваше решение без библиотеки на самом деле самое быстрое, оно занимает примерно вдвое меньше времени, чем моя реализация в том же тесте. К моему удивлению, различия в использовании памяти довольно малы, самый быстрый экономит всего около 10% памяти.
Ответ №2:
itertools.groupby
Функция в стандартной библиотеке предоставляет необходимую вам базовую функциональность. Затем нужно дать ему правильный ключ и подсчитать количество в каждой группе.
Вот моя реализация:
from itertools import groupby
def tally_by_group(keys, counts):
groups = groupby(zip(keys, counts), key=lambda x: x[0])
tallies = [
(key, sum(count for _, count in group))
for key, group in groups
]
return tuple(list(l) for l in zip(*tallies))
Объяснение кода:
- мой первый
zip()
создает (key, count) кортежи из двух списков, groupby
группирует их по первому элементу каждого кортежа, т.Е. По ключу,- затем я создаю список (ключ, сумма (количество)) в
tallies
, - и, наконец, распакуйте это обратно в два списка для получения результатов.
Тесты с вашими примерами:
lst1 = ["A", "A", "B", "A", "C", "D"]
lst2 = [1, 2, 3, 4, 5, 6]
l1m, l2m = tally_by_group(lst1, lst2)
print(l1m)
print(l2m)
выводит:
['A', 'B', 'A', 'C', 'D']
[3, 3, 4, 5, 6]
И
lst3 = ["A", "A", "A", "B", "B", "A", "A"]
lst4 = [1, 2, 3, 4, 5, 6, 7]
l3m, l4m = tally_by_group(lst3, lst4)
print(l3m)
print(l4m)
выводит:
['A', 'B', 'A']
[6, 9, 13]
Комментарии:
1. Я думал, что Pandas может сделать это более простым, но на самом деле это не так .