Добавление значений в список, если они одинаковые, с поворотом

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 может сделать это более простым, но на самом деле это не так .