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

How do I count the number of times an item in list be occurs in list a?

The above example should return a value of 4.

Whilst writing this question, I thought of the following (which appears to work)

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)

But there must be a neater way using list comparisons or something?

Escribblings
  • 739
  • 5
  • 9
  • 17

7 Answers7

8

You can use built-in sum:

sum(i in b for i in a)

Output:

4
Chris
  • 29,127
  • 3
  • 28
  • 51
3

If you just want to count the number of elements that are in both lists (and you don't need to know how many times they occur in the other list) you can just use:

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

Or identically:

count = len(set(a) & set(b))
ruohola
  • 21,987
  • 6
  • 62
  • 97
3

Simple way using set:

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

This is an old question, take a look to: How can I compare two lists in python and return matches

Juan Antonio
  • 2,451
  • 3
  • 24
  • 34
  • The difference between this question and the one you link to is that I don't want to return the matching values, I just need to count how many there are. – Escribblings Apr 23 '19 at 12:17
  • Yeah, of course. I only say that compare lists (after you can count or not) is an old issue :) I hope I helped you. – Juan Antonio Apr 23 '19 at 12:25
  • 1
    Thank you. I'm so new to py, that sometimes I struggle to fish out the relevant code as a lot of examples often do something different than what I'm trying to do. – Escribblings Apr 23 '19 at 12:34
  • 1
    Ok, I've accepted both yours, and @Chris 's answer above as solutions to my question. I shall pay with both to see which suits me best. Thank you. – Escribblings Apr 23 '19 at 12:40
  • This is just exactly the same as my answer. – ruohola Apr 24 '19 at 10:32
2

Try this just in one line:

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

s will be 4 as output. Also, it supports duplicate items in a.

Mehrdad Pedramfar
  • 10,941
  • 4
  • 38
  • 59
  • 1
    This is unnecessarily inieficient, as you are computing the same count on each iteration. – yatu Apr 23 '19 at 11:22
2

Here are a few variations that count duplicates and ignore all values that aren't in 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

Responding to your comment about performance, here's a comparison between scanning a list and scanning a set in 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

First point to note: Python's no slouch at either. 1/4 second on an old laptop to scan 10 million list elements isn't bad. But it's still a linear scan.

Python sets are in a different class. If you take the // 1000 out of time_since(), you'll see that Python scans a 1-million member set 10 times in under a microsecond. You'll find other set operations are also lightning fast. Wherever sets apply in Python, use them: they're fantastic.

And if you're contemplating applying the above code to much bigger lists, where performance matters, the first thing to do might be to convert b to a set.

Nic
  • 1,518
  • 12
  • 26
  • Thank you, but that's a lot more code than I've used, is it more efficient? – Escribblings Apr 23 '19 at 12:19
  • It's more code because it gives you more options. `Counter` is pretty quick. A `set()` operation is the fastest if you're only interested in the presence or absence of each item in `a`. This being Python, you're in the wrong place if you want super-efficient. To be frank, I find efficiency is rarely an issue with Python. On the whole Python culture is more interested in clear, simple, maintainable code than top performance. – Nic Apr 23 '19 at 12:34
  • Fair enough. Thank you for the response. – Escribblings Apr 23 '19 at 12:36
1

This one-liner should work as well. Find the count of each element and sum those counts up

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

The outputs will be

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

Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40
  • This appears similar to @Mehrdad Pedramfar 's answer above, which was accused of being inefficient. I don't know enough to comment if that is the case though. – Escribblings Apr 23 '19 at 12:23
0

While set works for unique

List comprehension considers duplicates as well

a = [1,1]
b = [1,1]

count = len(set(a) & set(b)) 
count2 = sum(i in b for i in a)  
print(count, count2) 
1 2

[Program finished] 
Subham
  • 397
  • 1
  • 6
  • 14