Самый быстрый способ подсчета вхождений частичного списка - PullRequest
1 голос
/ 08 апреля 2020

Какой самый быстрый способ подсчета вхождений элементов от начальной позиции до конечной позиции.

 list = [a,b,c,c,d,c....] can be very long
 count(list,c, from = 2, till = 4) = 2.

мы могли бы сделать

 counter = 0
 for i in range(startpos, endpos):
        if symbol == list[i]:
            counter+= 1

или мы могли бы сделать

list[startpos:endpos].count(symbol)

Однако это все равно выглядит медленнее, чем в первом варианте, и скопирует большую часть списка

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

Есть ли более быстрый, более pythoni c способ добиться этого?

Ответы [ 3 ]

2 голосов
/ 08 апреля 2020

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

a = 2
pos = range(5,15)
d = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,]
total = sum(elem == a for idx,elem in enumerate(d) if idx in pos)

print(total)

Это не будет копировать список, но будет повторять полный оригинал. Быстро проверить, находится ли idx в range.

Развертывание l oop приведет к перерыву - если крепость крайне важна, вы должны рассчитать время для своих подходов:

maxpos = max(pos)
minpos = min(pos)
for idx,elem in enumerate(d):
    if idx < minpos:
        continue
    elif idx > pos:
        break

    # check elem and counts something up
        continue

Это может быть, а может и не быть быстрее, если вы тестируете только небольшую часть вашего списка - это ничего не изменит, если вы добавите последние элементы в ваш список, но если ваш список огромен и ваша целевая область «передняя» i sh - перерыв может сэкономить вам несколько циклов

2 голосов
/ 08 апреля 2020

Если вам нужно чистое решение Python, преобразование вашей первой опции в выражение генератора в функции sum, вероятно, будет наиболее эффективным решением для действительно большого списка:

sum(1 for i in range(startpos, endpos) if list[i] == symbol)

Другое такие опции, как итерации с начала списка, который тратит много времени на итерации за пределы желаемого диапазона, или срезы, которые включают создание копии, не будут столь эффективными, если список действительно большой.

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

import numpy as np

... # create your very large numpy array as lst

print(np.sum(lst[startpos:endpos] == symbol))
1 голос
/ 08 апреля 2020

Попробуйте это:

from collections import Counter
print(Counter(my_list[start:end]))

Вы можете преобразовать объект Counter в dict, если вы предпочитаете:

occurrences = dict(Counter(my_list[start:end]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...