Создать массив словарей из списка Python - PullRequest
0 голосов
/ 08 января 2019

Я хочу превратить список разбросанных значений в массив словарей.

Я пытаюсь составить список значений прогнозирования в Python, которые можно использовать с JSON API. Как только у меня будет словарь, я буду использовать json.dumps.

my_list = [35, 2.75, 67, 3.45] # in form of: (value, score, value, score)

Идеальный результат:

my_array_of_dicts = [{'value':35, 'score':2.75}, {'value':67 'score':3.45}]

Вот что я пробовал.

Первая попытка:

d = dict(zip(my_list[::2], my_list[1::2]))

И это производит ...

> {35: 2.75,
   67: 3.45}

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

Вторая попытка:

[{'value':i, 'score':i} for i in my_list]]

> [{'value':35, 'score':35}, {'value':2.75, 'score':2.75}, 
   {'value':67, 'score':67}, {'value':3.45, 'score':3.45}] 

Это близко, но оно не учитывает каждую секунду, значение которой является баллом.

Ответы [ 7 ]

0 голосов
/ 08 января 2019

Попробуйте это:

my_list = [35, 2.75, 67, 3.45]
list_of_dicts = [{'value': k, 'score': v} for k, v in zip(iter(my_list), iter(my_list))]
print(list_of_dicts)

Выход:

[{'value': 35, 'score': 2.75}, {'value': 67, 'score': 3.45}]

Небольшое сравнение времени между моим решением и решениями других, которые используют нарезку списка:

In [1]: my_list = [35, 2.75, 67, 3.45] * 100 # making it longer for better testing results

In [2]: def zip_with_slice():
   ...:     return [{'value': v, 'score': s} for v, s in zip(my_list[::2], my_list[1::2])]
   ...:

In [3]: def zip_with_iter():
   ...:     return [{'value': k, 'score': v} for k, v in zip(iter(my_list), iter(my_list))]
   ...:

In [4]: %timeit zip_with_slice()
56.5 µs ± 1.27 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [5]: %timeit zip_with_iter()
93 µs ± 2.99 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Как видите, моё решение с использованием итераторов намного (в 5-6 раз) быстрее, чем решения, использующие нарезку.

0 голосов
/ 08 января 2019

Другой способ сделать это, используя dict с аргументами (**kwargs**):

>>> my_list = [35, 2.75, 67, 3.45]
>>> [dict(value=x,score=y) for x,y in zip(my_list[::2], my_list[1::2])]
[{'value': 35, 'score': 2.75}, {'value': 67, 'score': 3.45}]
>>> 
0 голосов
/ 08 января 2019

Использование списка понимания:

>>> my_list = [35, 2.75, 67, 3.45]
>>> my_dict = [{'value': my_list[i], 'score': my_list[i+1]} for i in range(0, len(my_list), 2)]
>>> my_dict
[{'score': 2.75, 'value': 35}, {'score': 3.45, 'value': 67}]
0 голосов
/ 08 января 2019
d = map(dict, map(lambda t:zip(('value','score'),t), zip(my_list[::2], my_list[1::2])))
print(list(d))
0 голосов
/ 08 января 2019

Вы действительно близки с версией zip. Вам просто нужно сделать объект и указать ключи.

my_list = [35, 2.75, 67, 3.45] 

[{'value': v, 'score': s} for v, s in zip(my_list[::2], my_list[1::2])]

результат:

[{'value': 35, 'score': 2.75}, {'value': 67, 'score': 3.45}]
0 голосов
/ 08 января 2019

Однострочник с использованием понимания:

[{'value': k, 'score': v} for k, v in [my_list[i: i + 2] for i in range(0, len(my_list), 2)]]

[{'score': 2.75, 'value': 35}, {'score': 3.45, 'value': 67}]

Используя вашу первоначальную попытку:

[{'value': k, 'score': v} for k,v in zip(my_list[::2], my_list[1::2])]

Еще один более многословный способ

from operator import itemgetter

getters = [itemgetter(slice(i, i + 2)) for i in range(0, len(my_list), 2)]
vals = [g(my_list) for g in getters]


def score_vals(s):
    k, v = s
    return {'value': k, 'score': v}

list(map(score_vals, vals))
0 голосов
/ 08 января 2019

Во второй попытке наберите: i + 1. В цикле сделайте для i в диапазоне (0, len (my_list), 2).

...