Daniel Bourke
Daniel Bourke

Reputation: 406

Create an array of dictionaries from a Python list

I want to turn a list of interspersed values into an array of dictionaries.

I'm trying to make a list of prediction values in Python capable to be used with a JSON API. Once I have the dictionary, I'll use json.dumps on it.

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

Ideal outcome:

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

Here's what I've tried.

First attempt:

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

And it produces...

> {35: 2.75,
   67: 3.45}

I'm not sure how to get custom keys. Or have each pair as its own dictionary.

Second attempt:

[{'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}] 

It's close but it doesn't account for every second value being a score.

Upvotes: 5

Views: 11304

Answers (8)

ElhamMotamedi
ElhamMotamedi

Reputation: 219

class my_dictionary(dict):

    # __init__ function
    def __init__(self):
        self = dict()

    # Function to add key:value
    def add(self, key, value):
        self[key] = value


# Main Function
dict_obj = my_dictionary()

Then you can assign values saved in tmpkey and tmpvalue to key value pairs in dictionary with the following code.

dict_obj.key = tmpkey
dict_obj.value = tmpvalue
dict_obj.add(dict_obj.key, dict_obj.value)

And for creating a list of dictionary all you need is to create an empty list and assign copy of your dictionary in each element of the list.

dicMatrix = []
dictionary_copy = dict_obj.copy()
dicMatrix.append(dictionary_copy)

In this way your dictionary will grow dynamically and the reason behind making a copy of dictionary is that if you will change the values of the dictionary each time the new value will be added to the list, otherwise the reference to the dictionary will be assigned to the list.

Upvotes: 0

gold_cy
gold_cy

Reputation: 14216

One-liner using comprehension:

[{'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}]

Using your original attempt:

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

Another more verbose way

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))

Upvotes: 2

iz_
iz_

Reputation: 16593

Try this:

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)

Output:

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

A little timing comparison between my solution and the solutions by others that use list slicing:

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)

As you can see, my solution using iterators is quite a bit (5-6x) faster than solutions using slicing.

Upvotes: 3

U13-Forward
U13-Forward

Reputation: 71580

Another way to do this, using dict with arguments (**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}]
>>> 

Upvotes: 2

Max Collier
Max Collier

Reputation: 691

Using List Comprehension:

>>> 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}]

Upvotes: 2

smallcat31
smallcat31

Reputation: 344

d = map(dict, map(lambda t:zip(('value','score'),t), zip(my_list[::2], my_list[1::2])))
print(list(d))

Upvotes: 3

Mark
Mark

Reputation: 92440

You're really close with the zip version. You just need to make the object and specify the keys.

my_list = [35, 2.75, 67, 3.45] 

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

result:

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

Upvotes: 6

Andrew Ray
Andrew Ray

Reputation: 186

In your second attempt, do score: i + 1. In the loop do for i in range(0, len(my_list), 2).

Upvotes: 3

Related Questions