iterating over values list in Python dictionary - python

Hi I am looking to iterate over a Python dictionary where each key has a list of values, I am looking to either create a new list/dictionary where I have separated each value[x] or directly do stuff with the separated values.
here's a simplified example of the dictionary I have:
all_parameters = {"first": ["1a","1b","1c"], "second": ["2a","2b","2c"], "third": ["3a","3b","3c"]}
I am looking to separate the values like this (either by creating a new dictionary or list or directly doing stuff with the separated values).
grouped_parameters = [{"first": "1a", "second": "2a", "third": "3a"},
{"first": "1b", "second": "2b", "third": "3b"},
{"first": "1c", "second": "2c", "third": "3c"}]
I am insure how to iterate correctly over each key:value pair.
i = 0
for k, v in all_parameters.items():
for item in v:
# stuck here
i+=1
Eventually the 'stuff' I am looking to do is convert each output (e.g. '{"first": "1a", "second": "2a", "third": "3a"}') into a string so that I can post each parameter group to a cell in a table, so ideally i'd prefer to do this dynamically instead of creating a new dictionary.
Any help would be greatly appreciated.

Assuming all lists have the same length:
>>> length = len(next(all_parameters.itervalues()))
>>> [{k:v[i] for k,v in all_parameters.iteritems()} for i in range(length)]
[{'second': '2a', 'third': '3a', 'first': '1a'}, {'second': '2b', 'third': '3b', 'first': '1b'}, {'second': '2c', 'third': '3c', 'first': '1c'}]
In Python 3, use len(next(iter(all_parameters.values()))) and items instead of iteritems.
(The iterator shenanigans are done because you don't need a list of all the dictionary values if you only want the length of an arbitrary value-list.)

If there's a chance of the lists being of different length, you could use map with None like so:
all_parameters = {"first": ["1a", "1b", "1c", "1d"], "second": ["2a", "2b", "2c"], "third": ["3a", "3b", "3c"]}
final = [dict(zip(all_parameters.keys(), values)) for values in map(None, *all_parameters.values())]
print final
map(None, *all_parameters.values()) gives you a tuple of the values for each key at each index - e.g. ('1a', '2a', '3a'), and by zipping this to the keys and creating a dictionary, we get the required combination.
Note: this will only work in Python 2.x as map changed in 3.x. For Python 3.x we can use itertools.zip_longest:
from itertools import zip_longest
all_parameters = {"first": ["1a", "1b", "1c", "1d"], "second": ["2a", "2b", "2c"], "third": ["3a", "3b", "3c"]}
final = [dict(zip(all_parameters.keys(), values)) for values in zip_longest(*all_parameters.values())]
print(final)
In both cases we get:
[{'second': '2a', 'third': '3a', 'first': '1a'}, {'second': '2b', 'third': '3b', 'first': '1b'}, {'second': '2c', 'third': '3c', 'first': '1c'}, {'second': None, 'third': None, 'first': '1d'}]

The items in a plain dict aren't ordered *, so you need to be careful when converting a dict to a string if you want the fields to be in a certain order.
This code uses a tuple containing the key strings in the order we want them to be in in the output dict strings.
all_parameters = {
"first": ["1a","1b","1c"],
"second": ["2a","2b","2c"],
"third": ["3a","3b","3c"],
}
# We want keys to be in this order
all_keys = ("first", "second", "third")
# Assumes all value lists are the same length.
for t in zip(*(all_parameters[k] for k in all_keys)):
a = ['"{}": "{}"'.format(u, v) for u, v in zip(all_keys, t)]
print('{' + ', '.join(a) + '}')
output
{"first": "1a", "second": "2a", "third": "3a"}
{"first": "1b", "second": "2b", "third": "3b"}
{"first": "1c", "second": "2c", "third": "3c"}
How it works
We first use a generator expression (all_parameters[k] for k in all_keys) which yields the value lists from all_parameters in the order specified by all_keys. We pass those lists as args to zip using the * "splat" operator. So for your example data, it's equivalent to calling zip like this:
zip(["1a","1b","1c"], ["2a","2b","2c"], ["3a","3b","3c"])
zip effectively transposes the iterables you pass it, so the result of that call is an iterator that produces these tuples:
('1a', '2a', '3a'), ('1b', '2b', '3b'), ('1c', '2c', '3c')
We then loop over those tuples one by one, with the for t in zip(...), so on the first loop t gets the value ('1a', '2a', '3a'), then ('1b', '2b', '3b'), etc.
Next we have a list comprehension that zips the value strings up with the corresponding key string and formats them into a string with double-quotes around each key and value string. We then join those strings together with commas and spaces as separators (and add brace characters) to make our final dict strings.
* Actually in Python 3.6 plain dicts do retain insertion order, but that is currently an implementation detail, and it should not be relied upon.

I'm not sure if this is what you want but
for i in range(len(all_parameters['first'])):
for position in all_parameters:
print(position+" "+all_parameters[position][i])
gives an output like this
first 1a
second 2a
third 3a
first 1b
second 2b
third 3b
first 1c
second 2c
third 3c
This will work only if each dictionary element has a list the same size as the first one.

Related

sort a list of dictionaries based on explicitly defined order of keys

I have a list of dictionary for ex:
names = [{'Mark':'Volvo'}, {'John':'BMW'}, {'Eliza':'Merci'}, {'Calen':'Audi'}]
I would like to set the explicit ordering by the key names of the dictionary.
For example if I give this order:
['John','Mark','Calen','Eliza']
The expected output would be:
[{'John':'BMW'},{'Mark':'Volvo'},{'Calen':'Audi'},{'Eliza':'Merci'}]
I want to add a custom logic order. To be displayed through the template by their names, based on how I defined the order of their names.
Similar to Is there a way to sort a list of string by a “predicate” list?: Since names is a list of dictionaries with just one key-value pair each, use the index of the person's name in the order list as the key for the sort:
>>> names = [{'Mark': 'Volvo'}, {'John': 'BMW'}, {'Eliza': 'Merci'}, {'Calen' :'Audi'}]
>>> order = ['John', 'Mark', 'Calen', 'Eliza']
>>>
>>> # with `sorted()`
>>> sorted(names, key=lambda d: order.index(list(d.keys())[0]))
[{'John': 'BMW'}, {'Mark': 'Volvo'}, {'Calen': 'Audi'}, {'Eliza': 'Merci'}]
>>>
>>> # or with `list.sort()`
>>> names.sort(key=lambda d: order.index(list(d.keys())[0]))
>>> names
[{'John': 'BMW'}, {'Mark': 'Volvo'}, {'Calen': 'Audi'}, {'Eliza': 'Merci'}]
dict.keys() is not not subscriptable, so dict.keys()[0] doesn't work. So first convert that to a list and then use its one-and-only key list(dict.keys())[0]. That would give 'Mark', 'John', etc. Then get the index of that person's name in the order list. Note: it will fail if a person is not listed in order.
Even if names is a list of dictionaries with more than one key-value pair each, as long as the person's name is the first key, it will still work as of Python 3.7/3.6. See the note below this item:
Changed in version 3.7: Dictionary order is guaranteed to be insertion order. This behavior was an implementation detail of CPython from 3.6.
>>> names = [{'Mark': 'Volvo', 'age': 30},
... {'John': 'BMW', 'age': 40},
... {'Eliza': 'Merci', 'age': 50},
... {'Calen': 'Audi', 'age': 60}]
>>> sorted(names, key=lambda d: order.index(list(d.keys())[0]))
[{'John': 'BMW', 'age': 40}, {'Mark': 'Volvo', 'age': 30}, {'Calen': 'Audi', 'age': 60}, {'Eliza': 'Merci', 'age': 50}]
>>>
First, if your dictionaries only have one entry, tuples seem to be a better choice for this data:
>>> names = [('Mark', 'Volvo'), ('John', 'BMW'), ('Eliza', 'Merci'), ('Calen', 'Audi')]
Now, given this order:
>>> order = ['John', 'Mark', 'Calen', 'Eliza']
you can create a dict that maps the names to the indices:
>>> order_map = { k: v for v, k in enumerate(order) }
>>> order_map
{'John': 0, 'Mark': 1, 'Calen': 2, 'Eliza': 3}
and use it in a key function for sort:
>>> names.sort(key=lambda v: order_map[v[0]])
>>> names
[('John', 'BMW'), ('Mark', 'Volvo'), ('Calen', 'Audi'), ('Eliza', 'Merci')]
names = [{'Mark':'Volvo'}, {'John':'BMW'}, {'Eliza':'Merci'}, {'Calen':'Audi'}]
ordered_keys = ['John','Mark','Calen','Eliza']
sorted_names = [name for key in ordered_keys for name in names if key in name]
It iterates over the ordered_keys in order and extracts any name in the list of dict that has that key.

Sorting a Dictionary by Nested Key

Consider a dict of the following form:
dic = {
"First": {
3: "Three"
},
"Second": {
1: "One"
},
"Third": {
2:"Two"
}
}
I would like to sort it by the nested dic key (3, 1, 2)
I tried using the lambda function in the following manner but it returns a "KeyError: 0"
dic = sorted(dic.items(), key=lambda x: x[1][0])
The expected output would be:
{
"Second": {
1: "One"
},
"Third": {
2: "Two"
},
"First": {
3:"Three"
}
}
In essence what I want to know is how to designate a nested key independently from the main dictionary key.
In the lambda function, x is a key-value pair, x[1] is the value, which is itself a dictionary. x[1].keys() is its keys, but it needs to be turned into a list if you want to get its one and only item by its index. Thus:
sorted(dic.items(), key = lambda x: list(x[1].keys())[0])
which evaluates to:
[('Second', {1: 'One'}), ('Third', {2: 'Two'}), ('First', {3: 'Three'})]
dic = {'First': {3: 'Three'}, 'Second': {1: 'One'}, 'Third': {2: 'Two'}}
sorted_list = sorted(dic.items(), key=lambda x:list(x[1].keys())[0])
sorted_dict = dict(sorted_list)
print(sorted_dict)
You need to get the keys for the nested dictionary first and then convert them into list and sort over its first index. You will get a sorted list. All you need to convert this list to dictionary using dict(). I hope that helps. This snippet works for python3.

Appending values to all keys of python dictionary

I have the following dictionary:
dic={'a': {'aa': [], 'ab': [], 'ac': []}, 'b': {'ba': [], 'bb': [], 'bc': []}}
I want to append three values to either all keys in 'a' or 'b'.
Following example works:
dic['a']['aa'].append(value_a)
dic['a']['ab'].append(value_b)
dic['a']['ac'].append(value_c)
Any way where I can do this in one single line.
What I'm searching for is something like the following:
dic['a'][*] = [value_a, value_b, value_c]
Where * is a wildcard indexing all keys in dic['a'].
As the complexity of the dictionary in my actual program grows my current working example becomes unreadable. So my motivation for this is mainly readability.
If a loop is acceptable for your single-line solution, then this may be used.
for key in dic['a']: dic['a'][key].append(value)
If you have a list of values, you can extend the list.
for key in dic['a']: dic['a'][key].extend([value_a, value_b, value_c])
To use a true one-liner (i.e., not writing a forloop in one line) it is possible to use map and exploit the mutability of dicts:
dic={'a': {'aa': [], 'ab': [], 'ac': []}, 'b': {'ba': [], 'bb': [], 'bc': []}}
vals = [1,2,3]
key = 'a'
map(lambda kv: dic[key][kv[0]].append(kv[1]), zip(dic[key], vals))
This will return [None, None, None] but the dict will be updated. However, I would suggest that it would be better to use an explicit for loop, as a two-liner:
for k, v in zip(dic[key], vals):
dic[key][k].append(v)
Note that this will add a separate value to each of the entries in the dict, as this is what I interpret to be what is wanted.

Get or delete value from a nested list in Python

I get 112 values from excel file. I transfer them to a dict, and then a list. They are grades from three exams based on student name.
Form like this :
grade = ["Mike", {"First": 0.9134344089913918, "Second": 0.9342180467620398, "Third": 0.8703466591191937}]
["Lisa", {"First": 0.8940552022848847, "Second": 0.9342180467620398, "Third": 0.881441786523737}]
["James", {"First": 0.8324328746220233, "Second": 0.9342180467620398, "Third": 0.683570699129642}]
Above are the first three set of value.
My goal is just obtain the first exam value from the list.
The result should be like this:
["Mike", {"First": 0.9134344089913918}]
["Lisa", {"First": 0.8940552022848847}]
["James", {"First": 0.8324328746220233}]
Two ways. a) delete the second and third exam value. b) just get the first exam value.
Is there anyone can help me. Since it is not a typical list...but it is not a dict. I use
print type(grade)....It shows its a list.
Thank you.
It is more natural to represent your initial structure as a dict (as well as the resulting structure).
all_grades = dict(grade)
Now, use a dict-comprehension, creating a new one-item-dict for each student:
first_grades = {
name: { 'First': grades_dict['First'] }
for name, grades_dict in all_grades.items()
}
Here's a generalisation of this concept:
first_grades = {
name: {
grade_key: grades_dict[grade_key]
for grade_key in ( 'First', )
}
for name, grades_dict in all_grades.items()
}
You end up with:
{'James': {'First': 0.8324328746220233},
'Lisa': {'First': 0.8940552022848847},
'Mike': {'First': 0.9134344089913918}}
grade = [["Mike", {"First": 0.9134344089913918, "Second": 0.9342180467620398, "Third": 0.8703466591191937}],["James", {"First": 0.8324328746220233, "Second": 0.9342180467620398, "Third": 0.683570699129642}]]
newdict=[]
for person,marks in grade:
print marks
newdict.append([person,{'First':marks['First']}])
#output [['Mike', {'First': 0.9134344089913918}], ['James', {'First': 0.8324328746220233}]]
please make sure your grades should be a list of list containing the person and marks as mine.then we can easily retrieve value
I'm not sure if I understand your data structure. You said you have a dict before you made a list. Maybe you could use this:
Data structure
>>> grade
{'Lisa': {'Third': 0.881441786523737, 'First': 0.8940552022848847, 'Second': 0.9
342180467620398}, 'Mike': {'Third': 0.8703466591191937, 'First': 0.9134344089913
918, 'Second': 0.9342180467620398}}
The result
>>> [{key:{'First':value['First']}} for key,value in grade.items()]
[{'Lisa': {'First': 0.8940552022848847}}, {'Mike': {'First': 0.9134344089913918}
}]

Sort a list of lists according to another list [duplicate]

This question already has answers here:
How to sort two lists (which reference each other) in the exact same way
(14 answers)
Closed 9 years ago.
How would you sort lista according to order of items in sorter_list:
lista = [["John", "B3"],["Robert", "P3"], ["Thomas", "S2"]]
sorter_list = ["P3", "S2", "B3"]
and result will be:
sorted_lista = [ ["Robert", "P3"], ["Thomas", "S2"], ["John", "B3"]]
Regards
Assuming there will always be an entry in sorter_list that matches the second element of each list in lista:
sorted_lista = sorted(lista, key=lambda lst: sorter_list.index(lst[1]))
Although #F.J has a perfect solution, my question is, why aren't you using a dictionary for storing this kind of data in the first place?
With dictionary:
d = {'B3': 'John', 'P3': 'Robert', 'S2': 'Thomas'}
sorter = ["P3", "S2", "B3"]
print([(d[key], key) for key in sorter])
Output:
[('Robert', 'P3'), ('Thomas', 'S2'), ('John', 'B3')]
Plus: You should also check the collections module's OrderedDict.
UPDATE:
Of course, you can store the values as lists, so one can hold multiple values:
With dictionary:
d = {'B3': [('John', 123)], 'P3': [('Robert', 465), ('Andres', 468)], 'S2': [('Thomas', 19)]}
sorter = ('P3', 'B3', 'S2')
print([(d[key], key) for key in sorter])
Output:
[([('Robert', 465), ('Andres', 468)], 'P3'), ([('John', 123)], 'B3'), ([('Thomas', 19)], 'S2')]
In this case, you can also use a dictionary inside a dictionary:
d = {'B3': {'John': 123}, 'P3': {'Robert': 465, 'Andres': 468}, 'S2': {'Thomas': 19}}
And the lookup will be much easier later on.
You can do this in O(N) by building a dictionary, where your keys are the B3, S2 etc.
lookup_dict = dict( (item[1],item) for item in lista)
sorted_lista = [ lookup_dict[key] for key in sorter_list ]
This takes advantage of the fact that your sorter_list is already sorted.
To sort efficient I think it's better to create a dictionary from sorter_list
sorter_dict = {x:i for i, x in enumerate(sorter_list)}
sorted_lista = sorted(lista, key=lambda lst: sorter_dict[lst[1]])
I'm newbie in python so it may not be the most optimized solution
sorted_lista=[]
for i in sorter_list:
for j in lista:
if i==j[1]:
sorted_lista.append([j[0],j[1]])
print sorted_lista
Output :
[['Robert', 'P3'], ['Thomas', 'S2'], ['John', 'B3']]

Categories