подсчитывать вхождения элементов списка во второй список в python - PullRequest
5 голосов
/ 23 апреля 2019
a = list([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
b = list([1, 3, 6, 9])

Как подсчитать, сколько раз элемент в списке встречается в списке a?

В приведенном выше примере должно возвращаться значение 4.

При написании этого вопросаЯ подумал о следующем (который, кажется, работает)

a = list([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
b = list([1, 3, 6, 9])
c = 0
for n in b:
    if n in a:
        c += 1
        continue
print (c)

Но должен быть более аккуратный способ использования сравнений списков или что-то еще?

Ответы [ 6 ]

6 голосов
/ 23 апреля 2019

Вы можете использовать встроенный sum:

sum(i in b for i in a)

Выход:

4
3 голосов
/ 23 апреля 2019

Простой способ использования set:

>>> len(set(a) & set(b))
4

Это старый вопрос, посмотрите: Как сравнить два списка в python и вернуть совпадения

2 голосов
/ 23 апреля 2019

Вот несколько вариантов, которые подсчитывают дубликаты и игнорируют все значения, которых нет в b.

from collections import Counter
# a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
a = [1, 4, 3, 1, 2, 4, 4, 5, 6, 6, 7, 7, 7, 7, 8, 9, 0, 1]
b = [1, 3, 6, 9]

counts = Counter()
# make counts order match b order
for item in b:
    counts[item] = 0
for item in a:
    if item in b:
        counts[item] += 1
print("in 'b' order")
print([(k, v) for k, v in counts.items()])
print("in descending frequency order")
print(counts.most_common())
print("count all occurrences in a of elements that are also in b")
print(sum(counts.values()))



python count_b_in_a.py
in 'b' order
[(1, 3), (3, 1), (6, 2), (9, 1)]
in descending frequency order
[(1, 3), (6, 2), (3, 1), (9, 1)]
count all occurrences in a of elements that are also in b
7

Отвечая на ваш комментарий о производительности, вот сравнение между сканированием списка и сканированием набора в Python:

import datetime

def timestamp():
    return datetime.datetime.now()


def time_since(t):
    return (timestamp() - t).microseconds // 1000


a = list(range(1000_000))
b = set(a)
iterations = 10
t = timestamp()
for i in range(iterations):
    c = 974_152 in a
print("Finished {iterations} iterations of list scan in {duration}ms"
      .format(iterations=iterations, duration=time_since(t)))
t = timestamp()
for i in range(iterations):
    c = 974_152 in b
print("Finished {iterations} iterations of set scan in {duration}ms"
      .format(iterations=iterations, duration=time_since(t)))

python scan.py
Finished 10 iterations of list scan in 248ms
Finished 10 iterations of set scan in 0ms

Первое замечание: у Python нет недостатка. 1/4 секунды на старом ноутбуке для сканирования 10 миллионов элементов списка - это неплохо. Но это все еще линейное сканирование.

Наборы Python находятся в другом классе. Если вы возьмете // 1000 из time_since(), вы увидите, что Python сканирует набор из 1 миллиона членов 10 раз за микросекунду. Вы найдете, что другие операции над множествами также молниеносны. Везде, где наборы применяются в Python, используйте их: они фантастические.

И если вы рассматриваете возможность применения приведенного выше кода в гораздо больших списках, где производительность важна, первое, что нужно сделать, это преобразовать b в набор.

2 голосов
/ 23 апреля 2019

Попробуйте это всего лишь одной строкой:

s = sum(a.count(i) for i in b if i in a)

s будет 4 в качестве вывода. Кроме того, он поддерживает дубликаты в a.

2 голосов
/ 23 апреля 2019

Если вы просто хотите посчитать количество элементов в обоих списках (и вам не нужно знать, сколько раз они встречаются в другом списке), вы можете просто использовать:

count = len(set(a).intersection(set(b)))

Или тождественно:

count = len(set(a) & set(b))
1 голос
/ 23 апреля 2019

Этот однострочный также должен работать.Найти количество каждого элемента и суммировать эти числа до

op = sum([a.count(j) for j in b])

Выходные данные будут

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
b = [1, 3, 6, 9]
#4
a = [1, 1, 2, 3, 3, 3, 4, 5, 6, 6 , 7, 8, 9, 0]
b = [1, 3, 6, 9]
#8

...