5

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.

8 Answers 8

6

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}]
Sign up to request clarification or add additional context in comments.

Comments

3

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

Comments

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

Comments

3

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.

3 Comments

@aws_apprentice You must have a quicker computer, because my tests show your edit at 57.8 µs.
@aws_apprentice I found the reason. I'm testing with the original list * 100 for more accurate results, while you are testing with the original list. This makes sense, as your solution doesn't look like an improvement.
@aws_apprentice Are you sure you are using the new, longer list? Also, your timeit doesn't seem fair, because you are doing the actual computation beforehand.
2

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

1 Comment

%timeit list(map(score_vals, vals)) isn't actually timing the whole computation, only a small portion of it.
2

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

Comments

2

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

Comments

0
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.