Суммируйте записи в List3 с индексом из List1, когда List1 == List2 - PullRequest
0 голосов
/ 28 января 2019

Поэтому я пытаюсь составить сумму из List3 на основе индекса из List1, когда List1 == List2.Я почти уверен, что проблема в List3[y] в начале этого оператора, но я не могу понять, что вместо этого поставить.

Это понимание состоит в том, чтобы заменить вложенный цикл, также опубликованный (который работаеткак и ожидалось).

Заранее спасибо.

#This loop works as intended, but takes a long time
for y in range(len(List1)):
    for x in range(len(List2)):
        if List1[y] == List2[x]:
            sumValue += List3[y]   


#Trying to build using this list comprehension sum
sumValue = sum([List3[y] for y, val1 in enumerate(List1) for x, val2 in enumerate(List2) if val1==val2])

1 Ответ

0 голосов
/ 29 января 2019

Сначала придерживайтесь PEP8 в именах переменных: list1 вместо List1.

Во-вторых, я думаю, что ваше понимание списка в порядке, но вы можете упростить его.

Примечание: я предполагаю, что len(list1) == len(list3).

Еслиэлементы list2 являются уникальными

Вы хотите знать, находится ли val1 в list2.Для этого есть оператор in:

sum([list3[i] for i, v in enumerate(list1) if v in list2])

Поиск значения в списке имеет O (n) временную сложность, но если вы преобразуете список в набор, сложность O(1):

set2 = set(list2)
sum([list3[i] for i, v in enumerate(list1) if v in set2])

Будет действительно быстрее .

Наконец, вы можете удалить скобки, поскольку sum принимает генератор:

set2 = set(list2)
sum(list3[i] for i, v in enumerate(list1) if v in set2)

Вот простой тест:

>>> list1=[random.randint(0,10000) for _ in range(10000)]
>>> list2=[random.randint(0,10000) for _ in range(10000)]
>>> list3=[random.randint(0,10000) for _ in range(10000)]
>>> timeit.timeit(lambda: sum(list3[i] for i, v in enumerate(list1) if v in list2), number=100)
61.139454132004175
>>> set2 = set(list2)
>>> timeit.timeit(lambda: sum(list3[i] for i, v in enumerate(list1) if v in set2), number=100)
0.09698906799894758

Если вы хотите удалить индексы, вы можете использовать zip:

sum(v3 for v1, v3 in zip(list1, list3) if v1 in set2)

Эта версия кажется немного быстрее, чемпредыдущий:

>>> timeit.timeit(lambda: sum(v3 for v1, v3 in zip(list1, list3) if v1 in set2), number=100)
0.07421852700645104

Если элементы list2 не являются уникальными

Вы хотите узнать , сколько раз val1 находится в list2.(Это то, что вы кодируете: для каждого элемента list1[i], добавьте list3[i] для каждого элемента из list2, что равно list[i]: , если у вас есть 3 раза list1[i]в list2 добавьте 3 list3[i] к результату ).Вы можете использовать collections.Counter:

>>> import collections
>>> c2 = collections.Counter(list2)
>>> sum(v3*c2[v1] for v1, v3 in zip(list1, list3))

Счетчик сопоставляет каждый элемент list2 с его числом вхождений: есть c2[v1] значений v1 в list2.

Сложность времени одинакова.

...