Ленивая сортированная функция, тимсорт - PullRequest
0 голосов
/ 16 ноября 2018

Имея список из N (большое количество) элементов:

from random import randint

eles = [randint(0, 10) for i in range(3000000)]

Я пытаюсь наилучшим образом (производительность / затраченные ресурсы) реализовать эту функцию ниже:

def mosty(lst):
    sort = sorted((v, k) for k, v in enumerate(lst))
    count, maxi, last_ele, idxs = 0, 0, None, []
    for ele, idx in sort:
        if(last_ele != ele):
            count = 1
            idxs = []
        idxs.append(idx)
        if(last_ele == ele):
            count += 1
            if(maxi < count):
                results = (ele, count, idxs)
                maxi = count
        last_ele = ele
    return results

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

Вот эталонный тест с 300000 эл.

Но я думаю,Я мог бы улучшить, одна из причин - функция python3 sorted ( timsort ), если бы он возвращал генератор, мне не нужно было дважды просматривать список, верно?

Мои вопросыявляются:

Есть ли способ оптимизировать этот код?Как?
С ленивой сортировкой я уверен, что так и будет, я прав?Как можно реализовать ленивый тимсорт

Ответы [ 2 ]

0 голосов
/ 16 ноября 2018

Если вы хотите использовать NumPy, вы можете сделать что-то вроде этого:

arr = np.array(eles)
values, counts = np.unique(arr, return_counts=True)
ind = np.argmax(counts)
most_common_elem, its_count = values[ind], counts[ind]
indices = np.where(arr == most_common_elem)

НТН.

0 голосов
/ 16 ноября 2018

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

from collections import Counter
from random import randint

eles = [randint(0, 10) for i in range(30)]

counter = Counter(eles)
most_common_element, number_of_occurrences = counter.most_common(1)[0]
indices = [i for i, x in enumerate(eles) if x == most_common_element]

print(most_common_element, number_of_occurrences, indices)

и индексы (вторая итерация) можно найти лениво в выражении генератора:

indices = (i for i, x in enumerate(eles) if x == most_common_element)

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

from collections import Counter
from itertools import groupby
from operator import itemgetter

eles = [1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5]

counter = Counter(eles)
_key, group = next(groupby(counter.most_common(), key=itemgetter(1)))
most_common = dict(group)
indices = {key: [] for key in most_common}

for i, x in enumerate(eles):
   if x in indices:
        indices[x].append(i)

print(most_common)
print(indices)

вы, конечно, все равно можете сделать indices ленивым, как и выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...