Количество элементов в наборе Python

У меня есть список телефонных номеров, которые были набраны (nums_dialed). У меня также есть набор телефонных номеров, которые являются номерами в офисе клиента (client_nums). Как эффективно выяснить, сколько раз я звонил конкретному клиенту (всего)?

Например:

>>>nums_dialed=[1,2,2,3,3]
>>>client_nums=set([2,3])
>>>???
total=4

Проблема в том, что у меня большой набор данных: len(client_nums) ~ 10^5; и len(nums_dialed) ~10^3.

5 ответов

Решение

Какой клиент имеет 10^5 номера в его кабинете? Вы работаете на всю телефонную компанию?

Тем не мение:

print sum(1 for num in nums_dialed if num in client_nums)

Это даст вам как можно быстрее номер.


Если вы хотите сделать это для нескольких клиентов, используя один и тот же nums_dialed список, затем вы можете сначала кэшировать данные по каждому номеру:

nums_dialed_dict = collections.defaultdict(int)
for num in nums_dialed:
    nums_dialed_dict[num] += 1

Затем просто суммируйте их по каждому клиенту:

sum(nums_dialed_dict[num] for num in this_client_nums)

Это было бы намного быстрее, чем повторять весь список чисел для каждого клиента.

Использование коллекций. Счетчик из Python 2.7:

dialed_count = collections.Counter(nums_dialed)
count = sum(dialed_count[t] for t in client_nums)
>>> client_nums = set([2, 3])
>>> nums_dialed = [1, 2, 2, 3, 3]
>>> count = 0
>>> for num in nums_dialed:
...   if num in client_nums:
...     count += 1
... 
>>> count
4
>>> 

Должно быть достаточно эффективным даже для больших чисел, которые вы цитируете.

Это очень популярный способ сделать несколько комбинаций отсортированных списков за один проход:

nums_dialed = [1, 2, 2, 3, 3]
client_nums = [2,3]

nums_dialed.sort()
client_nums.sort()

c = 0
i = iter(nums_dialed)
j = iter(client_nums)
try:
    a = i.next()
    b = j.next()
    while True:
        if a < b:
            a = i.next()
            continue
        if a > b:
            b = j.next()
            continue
        # a == b
        c += 1
        a = i.next() # next dialed
except StopIteration:
    pass

print c

Потому что "set" - это неупорядоченная коллекция (не знаю, почему она использует хэши, а не двоичное дерево или отсортированный список), и это будет нечестно использовать там. Вы можете реализовать собственный "set" через "bisect", если вам нравятся списки или что-то более сложное, что приведет к упорядоченному итератору.

Метод, который я использую, состоит в том, чтобы просто преобразоватьsetвlistа затем используйтеlen()функция для подсчета его значений.

      set_var = {"abc", "cba"}
print(len(list(set_var)))

Выход:

      2
Другие вопросы по тегам