Python для цикла и словарь не работает должным образом - PullRequest
1 голос
/ 03 ноября 2019

Я создал программу, которая принимает список пользователей в разговоре и список сообщений в этом разговоре, содержащий каждое сообщение с атрибутом имя пользователя и время .

Что я намеревался сделать, это проверить, когда есть ответ (когда msgList[i].usnername != msgList[i-1].username), проверить, кто делает этот ответ и сколько минут это заняло, а затем сложить 1 в словарь, подсчитывающий ответы, которые потребовалисьdif минут

def getResponseTime(userList, msgList):
    thresholds = [5, 15, 30, 60, 120, "inf"]
    k = dict.fromkeys(thresholds, 0)
    avl = dict.fromkeys(userList, k)

    for i in range(len(msgList)):
        if msgList[i].username != msgList[i-1].username:
            # response
            dif = (msgList[i].time - msgList[i-1].time).total_seconds()/60
            if dif > 0 and dif <= 5:
                avl[msgList[i].username][5] += 1
            elif dif > 5 and dif <= 15:
                avl[msgList[i].username][15] += 1
            elif dif > 15 and dif <= 30:
                avl[msgList[i].username][30] += 1
            elif dif > 30 and dif <= 60:
                avl[msgList[i].username][60] += 1
            elif dif > 60 and dif <= 120:
                avl[msgList[i].username][120] += 1
            else:
                avl[msgList[i].username]["inf"] += 1

    return avl

И я получаю такой вывод:

{'Lau': {5: 8223, 15: 1758, 30: 493, 60: 318, 120: 181, 'inf': 10081}, 'Fco': {5: 8223, 15: 1758, 30: 493, 60: 318, 120: 181, 'inf': 10081}}

Как видите, результаты одинаковы для обоих пользователей, и я не могу найти ни одной ошибки вкод, который может объяснить это.

1 Ответ

0 голосов
/ 03 ноября 2019

Per https://docs.python.org/3/library/stdtypes.html?highlight=fromkeys#dict.fromkeys, второй аргумент fromkeys - это одно значение, на которое указывают все ключи, поэтому каждый из ваших ключей указывает на один и тот же словарь в памяти. Когда вы увеличиваете некоторое значение для того, что кажется одним пользователем, оно фактически увеличивает его для всех пользователей!

Вместо этого вы должны использовать вложенный defaultdict из модуля collections (https://docs.python.org/3/library/collections.html#collections.defaultdict).

Вот модификация:

import collections

def getResponseTime(userList, msgList):
    thresholds = [5, 15, 30, 60, 120, "inf"]
    avl = collections.defaultdict(lambda : collections.defaultdict(int))

    for i in range(len(msgList)):
        if msgList[i].username != msgList[i-1].username:
            # response
            dif = (msgList[i].time - msgList[i-1].time).total_seconds()/60
            if dif > 0 and dif <= 5:
                avl[msgList[i].username][5] += 1
            elif dif > 5 and dif <= 15:
                avl[msgList[i].username][15] += 1
            elif dif > 15 and dif <= 30:
                avl[msgList[i].username][30] += 1
            elif dif > 30 and dif <= 60:
                avl[msgList[i].username][60] += 1
            elif dif > 60 and dif <= 120:
                avl[msgList[i].username][120] += 1
            else:
                avl[msgList[i].username]["inf"] += 1

    return avl

avl теперь словарь, в котором, когда вы обращаетесь к ключу, который еще не существует, он указывает этот ключ на другой defaultdict для хранения пороговых чисел, который имеет то же поведение, за исключением того, что по умолчанию он равен 0, когда вы пытаетесь получить ключ, который не существует.

...