#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