Conversation
0xE111
left a comment
There was a problem hiding this comment.
Всё хорошо, но бонусное хорошо было бы переделать там где рекурсия. Но т.к. оно бонусное, то по желанию.
| @@ -0,0 +1 @@ | |||
| env | |||
There was a problem hiding this comment.
Обычно это файл .env (с точкой впереди)
| names = ['Оля', 'Петя', 'Вася', 'Маша'] | ||
| # ??? | ||
| for name in names: | ||
| gender = 'М' if is_male[name] else 'Ж' |
| for name in names: | ||
| for person in students_list: | ||
| if name == person: | ||
| count_dict[name] += 1 |
There was a problem hiding this comment.
Логика понятна, но это сильно неоптимально. Каждый проход по циклу стоит каких-то ресурсов, а тут аж цикл в цикле. Вообще вложенные циклы нужно стараться избегать, потому что пройти по циклу из N элементов - это N итераций, а по двум вложенным циклам - уже N*N - то есть квадратичная сложность.
В данном случае можно сделать что-то совсем простое, например, один раз (!) пройтись по студентам и увеличивать счётчик имени:
counter = {}
for student in students:
name = student['first_name']
try:
counter[name] += 1
except KeyError:
counter[name] = 1Если хочется чего-то покороче - можно посмотреть в сторону defaultdict.
| for key in counted.keys(): | ||
| val = counted[key] |
There was a problem hiding this comment.
Если нужны и ключ, и значение, то нужно сразу
for key, val in counterd.items():
...| # Вывести количество букв "а" в слове | ||
| word = 'Архангельск' | ||
| # ??? | ||
| print(len(word)) |
| def count_messages_by_key(history, key, pop_none = False): | ||
| items = list_val_by_key(history, key, pop_none = pop_none) | ||
| return count_repeated(items) |
There was a problem hiding this comment.
Тогда это превратится в
key = 'some-key'
values = [message[key] for message in history]
counter = Counter(values)| def find_biggest(data: dict): # {item : count} | ||
| listed_count = list(data.values()) # call values just once | ||
| most_index = listed_count.index(max(listed_count)) # get id in values list, | ||
| return list(data.keys())[most_index] # as we get the same order from keys as from values method we use the same id |
There was a problem hiding this comment.
Если использовали Counter, то
biggest = counter.most_common(1)[0]Если хочется вручную это сделать, то рекомендую просто использовать max() с аргументом key:
biggest = max(data, key=lambda x: data[x])Текущий вариан плох тем, что что там keys() и values() вызываются, то есть как минимум дважды проходимся по словарю. Лучше уж топорный вариант с сохранением самого большого элемента, он будет всё равно оптимальнее:
def find_biggest(data: dict):
biggest_item = None
biggest_count = 0
for item, count in data.items():
if count > biggest_count:
biggest_count = count
biggest_item = item
return biggest_item| for i, divider in enumerate(time_dividers): | ||
| if hour < divider: | ||
| output[i].append(hour) | ||
| found = True | ||
| break | ||
| if not found: # means given hour is after the last divider | ||
| output[-1].append(hour) |
There was a problem hiding this comment.
В таких случаях вместо found = True / False нужно использовать for - else:
for item in items:
if ...:
print("Something good happened")
break
else:
print("Nothing good happened")| def separate_datetime_by_hours(data: list, time_dividers: list): | ||
| ''' | ||
| Accepts datetime list and intervals dividers, | ||
| returns a list of time lists sorted on intervals by hours | ||
| ''' | ||
|
|
There was a problem hiding this comment.
Огромное увеличение сложности, только чтобы потом красиво вызвать
separated_dates = separate_datetime_by_hours(dates, [12, 18])Имхо не стоит того. Можно просто сделать функцию для категоризации:
def get_part_of_day(dt) -> Literal['morning', 'day', 'evening']:
if 0 <= dt.hour < 9:
return 'morning'
if 9 <= dt.hour < 18:
return 'day'
return 'evening' И потом уже её использовать:
messages_by_part_of_day = {
'morning': 0,
'day': 0,
'evening': 0,
}
for dt in data:
part_of_day = get_part_of_day(dt)
messages_by_part_of_day[part_of_day] += 1Гораздо проще читать и понимать.
| reply_for_ids = list_val_by_key(history, 'reply_for', pop_none=True) | ||
| treads = {} | ||
|
|
||
| for reply_for_id in reply_for_ids: | ||
| tread = [] | ||
| recursive_search_and_stack(reply_for_id, history, tread) | ||
| treads[tread[-1]] = len(tread) | ||
|
|
||
| longest_dialog_start_id = find_biggest(treads) |
There was a problem hiding this comment.
Тут сначала мы полностью проходим по всем сообщениям, только чтобы собрать их reply_for, а потом в цикле for reply_for_id in reply_for_ids вызываем рекурсивную recursive_search_and_stack, которая в цикле проходит по всем сообщениям. Такой код будет работать дома на компьютере, но как только уйдёт в работу, сразу взорвётся на реальных данных, когда там будет тысяча сообщений.
Это совершенно точно нужно отрефакторить, чтобы был один, ну максимум два прохода по history, но не больше.
No description provided.