Множественный словарь присваивания списка значений с одним циклом for для нескольких ключей - PullRequest
0 голосов
/ 20 мая 2019

Я хочу создать словарь со списком значений для нескольких ключей с одним циклом for в Python3. Для меня время выполнения и объем памяти имеют первостепенное значение, поскольку файл, который читает мой скрипт на Python3, довольно длинный.

Я уже пробовал следующий простой скрипт:

p_avg = []
p_y = []
m_avg = []
m_y = []
res_dict = {}

with open('/home/user/test', 'r') as f:
    for line in f: 
        p_avg.append(float(line.split(" ")[5].split(":")[1]))
        p_y.append(float(line.split(" ")[6].split(":")[1]))
        m_avg.append(float(line.split(" ")[1].split(":")[1]))
        m_avg.append(float(line.split(" ")[2].split(":")[1]))

res_dict['p_avg'] = p_avg
res_dict['p_y'] = p_y
res_dict['m_avg'] = m_avg
res_dict['m_y'] = mse_y

print(res_dict)

Формат моего home/user/test файла:

n:1 m_avg:7588.39 m_y:11289.73 m_u:147.92 m_v:223.53 p_avg:9.33 p_y:7.60 p_u:26.43 p_v:24.64
n:2 m_avg:7587.60 m_y:11288.54 m_u:147.92 m_v:223.53 p_avg:9.33 p_y:7.60 p_u:26.43 p_v:24.64
n:3 m_avg:7598.56 m_y:11304.50 m_u:148.01 m_v:225.33 p_avg:9.32 p_y:7.60 p_u:26.43 p_v:24.60
.
.
.

Сценарий Python, показанный выше, работает, но сначала он слишком длинный и повторяющийся, во-вторых, я не уверен, насколько он эффективен. В конце концов я подумал создать то же самое со списком. Примерно так:

(res_dict['p_avg'], res_dict['p_y']) = [(float(line.split(" ")[5].split(":")[1]), float(line.split(" ")[6].split(":")[1])) for line in f]

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

[РЕДАКТИРОВАТЬ] Я изменил dict -> res_dict, так как было упомянуто, что это не очень хорошая практика, я также исправил опечатку, где p_y не указывал на правильное значение и добавил оператор печати для печати результирующего словаря, упомянутого другими пользователями.

Ответы [ 3 ]

2 голосов
/ 20 мая 2019

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

from collections import defaultdict

res = defaultdict(list)

with open('/home/user/test', 'r') as f:
    for line in f: 
        items = line.split()
        extract = lambda x: x.split(':')[1]

        res['p_avg'].append(extract(items[5]))
        res['p_y'].append(extract(items[6]))
        res['m_avg'].append(extract(items[1]))
        res['m_y'].append(extract(items[2]))
1 голос
/ 20 мая 2019

Вы можете просто предварительно определить атрибуты dict:

d = {
    'p_avg': [],
    'p_y': [],
    'm_avg': [],
    'm_y': []
}

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

with open('/home/user/test', 'r') as f:
    for line in f:
        splitted_line = line.split(" ")
        d['p_avg'].append(float(splitted_line[5].split(":")[1]))
        d['p_y'].append(float(splitted_line[5].split(":")[1]))
        d['m_avg'].append(float(splitted_line[1].split(":")[1]))
        d['m_avg'].append(float(splitted_line[2].split(":")[1]))

P.S. Никогда не используйте имена переменных, равные встроенным словам, такие как dict, list и т. Д. Это может привести к МНОГИМ различным ошибкам!

1 голос
/ 20 мая 2019

Вы можете инициализировать ваш dict, чтобы он содержал пары строка / список, а затем добавлять непосредственно при выполнении итерации по каждой строке.Кроме того, вы не хотите продолжать вызывать split() на line на каждой итерации.Скорее просто вызовите один раз и сохраните в локальной переменной и индексируйте из этой переменной.

# Initialize dict to contain string key and list value pairs
dictionary = {'p_avg':[],
              'p_y':[],
              'm_avg':[],
              'm_y':[]
             }
with open('/home/user/test', 'r') as f:
    for line in f:
        items = line.split() # store line.split() so you don't split multiple times per line
        dictionary['p_avg'].append(float(items[5].split(':')[1]))
        dictionary['p_y'].append(float(items[6].split(':')[1])) # I think you meant index 6 here
        dictionary['m_avg'].append(float(items[1].split(':')[1]))
        dictionary['m_y'].append(float(items[2].split(':')[1]))
...