Есть ли какой-либо способ ускорить эту функцию

#python #loops #list-comprehension

#python #циклы #список-понимание

Вопрос:

Я пишу эту функцию, и сначала я использовал циклы. Циклы требуют времени для того, чтобы я попробовал понять список. Это не сработало. Для этой функции разрешено 10 секунд. Пожалуйста, проверьте это. Функция возвращает отсортированный список компаний, где их соотношение составляет 5% или более.

 def mostActive(customers):
    # Write your code here
    tot = len(customers)
    set_cust = set(customers)
    cust_dict = {i: customers.count(i)/tot for i in set_cust}
    cus_list = [i for i in list(cust_dict) if cust_dict[i] >= 0.05]
    return sorted(cus_list)
  

Пример ввода и вывода

 Omega
Alpha
Omega
Alpha
Omega
Alpha
Omega
Alpha
Omega
Alpha
Omega
Alpha
Omega
Alpha
Omega
Alpha
Omega
Alpha
Omega
Beta
  

Ожидаемый результат:

 Alpha
Beta
Omega
  

Комментарии:

1. и почему бы просто не использовать collections.Counter ?

2. не хочу использовать какую-либо библиотеку, просто чистый Python

3. тогда вам следует изучить стандартную библиотеку Python, потому что это часть стандартной библиотеки

4. Как сказал @buran, collections.Counter является частью стандартной библиотеки, поэтому это чистый python, и он справится.

5. … он справится с вашим случаем лучше, чем реализовать его самостоятельно.

Ответ №1:

В качестве альтернативы вы также можете использовать collections.Counter

 from collections import Counter

tot = len(customers)
[k for k, v in Counter(customers).items() if (v / tot >= 0.05)]
  

Комментарии:

1. просто чистый python

2. Это встроенные функции Python.

3. Вам не хватает отсортированной части, Counter не имеет гарантии упорядочения, не так ли?

4. @Adrilio — вывод примера OP не показывает результат в отсортированном порядке. Если это имеет значение, я бы использовал Counter.most_common() метод и, вероятно itertools.takewhile

5. @buran это так, он также упоминает это в вопросе и имеет sorted в предоставленном коде. Сортируется по имени, а не по частоте.

Ответ №2:

Эту строку необходимо оптимизировать:

 cust_dict = {i: customers.count(i)/tot for i in set_cust}
  

Это квадратично по количеству клиентов, потому что customers.count(i) будет выполняться итерация по всему customers списку для каждого клиента в set_cust .

Вместо этого вы можете выполнить цикл customers один раз и отслеживать счетчики в словаре, а затем разделить на tot в конце.

Комментарии:

1. Я не знал, что customerns.count() выполняет итерацию по всему списку.

2. @shahidhamdam если вам нужно посчитать, сколько красных шариков у вас в мешке с шариками, как вы думаете, сможете ли вы сделать это, не видя всех шариков? Измените красные шары на i и все шары на customers .

3. Создание a, dict ключами которого являются элементы, а значениями — время появления каждого элемента, — это именно a, collections.Counter так что вы, по сути, изобретаете велосипед. collections.Counter будет намного более оптимизирован, чем ваша версия, является частью стандартной библиотеки (чистый python, как вы говорите) и допускает дальнейшие улучшения, такие как использование most_common() и разрыв при первом обнаружении менее 5%, поскольку каждый следующий элемент также будет меньше 5%, например.

Ответ №3:

Альтернативный объектно-ориентированный подход:

 from collections import Counter


class FreqCounter(Counter):
    def most_common(self, *args, **kwargs):
        total = sum(self.values())
        return list(map(lambda x: (x[0], x[1]/total), super().most_common(*args, **kwargs)))


def most_active(customers):
    most_active_customers = []
    for customer, freq in FreqCounter(customers).most_common():
        if freq < 0.05:
            break
        most_active_customers.append(customer)
    return sorted(most_active_customers)  # Remove sorted if needed in frequency order instead of name order


customers = [
    'Omega', 'Alpha', 'Omega', 'Alpha', 'Omega',
    'Alpha', 'Omega', 'Alpha', 'Omega', 'Alpha',
    'Omega', 'Alpha', 'Omega', 'Alpha', 'Omega',
    'Alpha', 'Omega', 'Alpha', 'Omega', 'Beta',
]
for customer in most_active(customers):
    print(customer)
  

Выводит:

 Alpha
Beta
Omega
  

Удалив sorted в соответствии с инструкциями, результат будет:

 Omega
Alpha
Beta