Распаковка списка на строки, их разбиение и создание оттуда словаря

Я использую python 3.x и хочу создать словарь из списка. То есть у меня каждый ключ и значение объединены в строку, а каждая запись - как элемент в списке.

my_list = ['val1 key1', 'val2 key2', 'val2 key2']

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

values,keys = zip(*(s.split() for s in my_list))

Создать словарь оттуда легко. Поскольку мне все еще нужно что-то делать с ключами и значениями, я делаю:

my_dict = {k[:-1]:float(v) for k,v in zip(keys,values)}

Из простого любопытства мне было интересно, есть ли способ избежать промежуточных списков. Короче говоря, мне нужно получить доступ к каждому элементу списка, разделить строку, сделать что-нибудь с каждой разделенной частью и ввести ее как пару ключ: значение в словарь. После вопроса это я попробовал

my_dict = {k[:-1]:float(v) for v,k in zip(*(s.split() for s in my_list))}

Но у меня ValueError: too many values to unpack (expected 2). Затем я попытался просто использовать генератор (я считать это генератор) внутри синтаксиса понимания словаря, и он работал. Но мне это не нравится, так как второй for используется только для извлечения элемента из списка:

my_dict = {s[1][:-1]:float(s[0]) for s in (s.split(', ') for s in my_list)}

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

EDIT1: исправлено несколько синтаксических ошибок, которые у меня были.

EDIT2: полный рабочий и явный пример с ожидаемым результатом, как предлагается. Я все еще работаю над созданием хороших mcve:

my_list = ['1.123, name1\n', '2.3234, name2\n', '3.983, name3\n', '4.23, name4\n']

Результат, который я хочу, - это то, что я получил бы, если бы вручную сделал

my_dict = {'name1':1.123, 'name2':2.3234, 'name3':3.983, 'name4':4.23}

Метод создания промежуточных списков:

values,keys = zip(*(s.split(', ') for s in my_list))
print(values)
>>> ('1.123', '2.3234', '3.983', '4.23')
print(keys)
>>> ('name1\n', 'name2\n', 'name3\n', 'name4\n')
my_dict = {k[:-1]:float(v) for k,v in zip(keys,values)}
print(my_dict)
>>> {'name4': 4.23, 'name2': 2.3234, 'name1': 1.123, 'name3': 3.983}

Пример, почему я не знаю, почему это не работает:

my_dict = {k[:-1]:float(v) for v,k in zip(*(s.split(', ') for s in my_list))}
>>> ValueError: too many values to unpack (expected 2)

Рабочий пример, который мне кажется, он использует один для for внутри выражения понимания / генератора списка / dict:

my_dict = {s[1][:-1]:float(s[0]) for s in (s.split(', ') for s in my_list)}
print(my_dict)
>>> {'name4': 4.23, 'name2': 2.3234, 'name1': 1.123, 'name3': 3.983}

Мои настоящие строки выглядят примерно как '0.9493432915614861, zf_AB012_bn_BOS\n' , поэтому я использую более читаемый пример.

EDIT3: я только что узнал о методе str.strip (). Это делает строку, создающую словарь, немного приятнее:

my_dict = {s[1].strip():float(s[0]) for s in (s.split(', ') for s in my_list)}

Один из элементов вашего списка содержит более двух частей, разделенных пробелами. Вероятно, использование s.split(maxsplit=1) исправляет ошибку.

Giacomo Alzetta 10.08.2018 16:48

Каков ваш желаемый результат? for zip(keys,values) - неверный синтаксис.

Ajax1234 10.08.2018 16:49

Вы также пытаетесь преобразовать v как float, но это строка.

Jim Wright 10.08.2018 16:50

Пожалуйста, опубликуйте пример ввода и желаемого результата.

Vasilis G. 10.08.2018 16:52

Я понял, что вы имели в виду, но предлагаю вам принять во внимание все эти комментарии и улучшить свой вопрос рабочим примером.

kabanus 10.08.2018 16:53

Спасибо за комментарии. @ Ajax1234, вы правы, исправили ошибку. Обновляю вопрос конкретным примером и ожидаемым результатом.

Puff 10.08.2018 18:51

Если вы используете Python 3 (а вы должны быть), zip на самом деле не будет создавать список, а вместо этого создаст итератор.

PMende 10.08.2018 19:54
1
7
132
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
def dict_unzip(lst):
    for x in lst:
        yield reversed(x.split(' ', 1))

my_dict = dict(dict_unzip(my_list))

Но поскольку это Python3, на самом деле все намного проще:

my_dict = dict(map(lambda s: reversed(s.split(' ', 1)), my_list))

Или даже

my_dict = dict(reversed(s.split(' ', 1)) for s in my_list)

Спасибо! map был тем, чего мне не хватало в моем репертуаре.

Puff 10.08.2018 18:55

Другие вопросы по теме