Sort a python dictionary based on input value? - python

I have a dictionary with four keys a,b,c,d with values 100,200,300,400
list1 = {'a':'100','b':'200','c':'300','d':'400'}
And a variable inputs.
inputs = 'c'
If inputs is c. The list1 dictionary has to be sorted based on it.
inputs = 'c'
list1 = {'c':'300','a':'100','b':'200','d':'400'}
inputs = 'b'
list1 = {'b':'200','a':'100','c':'300','d':'400'}

In Python3.7+ dict keys are stored in the insertion order
k ='c'
d={k:list1[k]}
for key in list1:
if key!=k:
d[key]=list1[key]
Output
{'c': '300', 'a': '100', 'b': '200', 'd': '400'}

Seems like you just want to rearrange your dict to have the chosen value at the front, then the remaining keys afterwards:
dict1 = {'a':'100','b':'200','c':'300','d':'400'}
key = 'c'
result = {key: dict1[key], **{k: v for k, v in dict1.items() if k != key}}
print(result)
# {'c': '300', 'a': '100', 'b': '200', 'd': '400'}
The ** simply merges the leftover filtered keys with key: dict1[key].

If you just want to change the position to the first one a given value if it exists, it could be done in the following way:
list1 = {'a':'100','b':'200','c':'300','d':'400'}
inputs = 'c'
output = {}
if inputs in list1.keys():
output[inputs] = list1.get(inputs)
for i in list1.keys():
output[i] = list1[i]
Output;
{'c': '300', 'a': '100', 'b': '200', 'd': '400'}

Here's a one-liner:
d = {'a':'100','b':'200','c':'300','d':'400'}
i = input()
d = {i:d[i],**{k:d[k] for k in d if k!=i}}
print(list1)
Input:
c
Output:
{'a': '100', 'b': '200', 'd': '400', 'c': '300'}

Related

Extract subset of dictionaries inside a list of dictionaries until particular key is found

I have a list of dict
dict = [{'a':'1'},{'b':'2'},{'c':'3'},{'Stop':'appending'},{'d':'4'},{'e':'5'},{'f':'6'}]
dict1 = [{'a':'1'},{'b':'2'},{'c':'3'},{'d':'4'},{'Stop':'appending'},{'e':'5'},{'f':'6'}]
I want to extract all list elements until key 'Stop' is found and append it to new dictionary
Expected output:
new_dict = [{'a':'1'},{'b':'2'},{'c':'3'}]
new_dict1 = [{'a':'1'},{'b':'2'},{'c':'3'},{'d':'4'}]
Code:
temp_dict = []
for i in range(0,len(list)):
for key,value in list[i].items():
if key == 'Stop':
break
temp_dict.append(list[i])
It's already in standard library
import itertools
dict1 = [{'a':'1'},{'b':'2'},{'c':'3'},{'d':'4'},{'Stop':'appending'},{'e':'5'},{'f':'6'}]
res = list(itertools.takewhile(lambda x: "Stop" not in x, dict1))
print(res)
output:
[{'a': '1'}, {'b': '2'}, {'c': '3'}, {'d': '4'}]
You can use enumerate() to get the index of the element matching the key Stop and then used list slicing on top of that:
dic = [{'a':'1'},{'b':'2'},{'c':'3'},{'Stop':'appending'},{'d':'4'},{'e':'5'},{'f':'6'}]
index = next(index for index, elt in enumerate(dic) if elt.get('Stop'))
new_dic = dic[0:index] # [{'a': '1'}, {'b': '2'}, {'c': '3'}]
Also, don't use dict keyword for object names to avoid shadowing built-in primitives.
Update: If you want to just skip the element with key Stop and take all others then update the above slicing operation as:
new_dic = dic[0:index] + dic[index+1:] # [{'a': '1'}, {'b': '2'}, {'c': '3'}, {'d': '4'}, {'e': '5'}, {'f': '6'}]
First find the index of the elements that have 'Stop' like a key, and after that just slice the list to the first of those index.
Try:
inds = [i for i in range(len(dict1)) if 'Stop' in dict1[i].keys()]
new_dict1 = dict1[:inds[0]]
Also, I think you should choice better names for your lists, especially for the first, dict is a reserved word in python.

Appending dictionary to list with different value same key

I have a list of dictionaries, that have same keys and some have different values for those keys. I am trying to append the dictionaries that have different values from the list to keep track of the different values and I would concatenate the values of other keys. For example, I am storing 'a' keys with same values and concatenating the 'b' values that have same 'a':'1'
input list: d = [{'a': '1', 'b': '3'}, {'a': '2', 'b': '4'}, {'a': '1', 'b':'5'}]
output list: p = [{'a':'1', 'b': '35'}, {'a': '2', 'b': '4'}]
So far, I tried the following code, but it doesnt recognize the different values
length = len(p)
j = 0
for i in d:
while j < length:
if p[j]['a'] is not i['a']:
p.append({'a', p[j]['a']})
else:
p[j]['b'] += i['b']
j += 1
j = 0
any tips would be appreciated
Use a dictionary that has the a values as its keys so you don't have to loop through the result list for a matching a.
temp_dict = {}
for item in d:
if item['a'] in temp_dict:
temp_dict[item['a']]['b'] += item['b']
else:
temp_dict[item['a']] = item.copy()
p = list(temp_dict.values())

How to use a dict comprehension to split a list?

I currently have a dict in the form:
data = {"var1":"600103", "var2":[{"a":"1","b":"2"}]}
I would like the output to be:
op = {"var1":"600103","var2[0]":{"a":"1","b":"2"}}
I am currently using loops to manually loop through. I'd like to know if there's a more pythonic way of doing this.
If this isn't what you're already doing, you can eliminate the need for a nested loop by using a dict comprehension for the values which are lists.
data = {"var1":"600103", "var2":[{"a":"1","b":"2"}, {"a":"22","b":"555"}]}
op = {}
for k in data:
if not isinstance(data[k], list):
op[k] = data[k]
else:
op.update({k + '[{}]'.format(i) : data[k][i] for i in range(len(data[k])) })
And, your output will look like this:
{'var1': '600103', 'var2[1]': {'a': '22', 'b': '555'}, 'var2[0]': {'a': '1', 'b': '2'}}
I do not know if it is very pythonic or not but I know for sure that it is difficult to read :S
Sorry, just playing... ;)
data = {"var1":"600103", "var2":[{"a":"1","b":"2"},{"a":"3","b":"4"},{"a":"5","b":"6"},{"a":"7","b":"8"}], "var3":"600103"}
reduce(
lambda a, b: dict(a.items() + b.items()),
[
dict(map(lambda (idx, i): ('{0}[{1}]'.format(key, idx), i), enumerate(value))) if type(value) is list else {key: value}
for key, value
in data.items()
]
)
output:
{'var1': '600103',
'var2[0]': {'a': '1', 'b': '2'},
'var2[1]': {'a': '3', 'b': '4'},
'var2[2]': {'a': '5', 'b': '6'},
'var2[3]': {'a': '7', 'b': '8'},
'var3': '600103'}

Converting colon separated list into a dict?

I wrote something like this to convert comma separated list to a dict.
def list_to_dict( rlist ) :
rdict = {}
i = len (rlist)
while i:
i = i - 1
try :
rdict[rlist[i].split(":")[0].strip()] = rlist[i].split(":")[1].strip()
except :
print rlist[i] + ' Not a key value pair'
continue
return rdict
Isn't there a way to
for i, row = enumerate rlist
rdict = tuple ( row )
or something?
You can do:
>>> li=['a:1', 'b:2', 'c:3']
>>> dict(e.split(':') for e in li)
{'a': '1', 'c': '3', 'b': '2'}
If the list of strings require stripping, you can do:
>>> li=["a:1\n", "b:2\n", "c:3\n"]
>>> dict(t.split(":") for t in map(str.strip, li))
{'a': '1', 'b': '2', 'c': '3'}
Or, also:
>>> dict(t.split(":") for t in (s.strip() for s in li))
{'a': '1', 'b': '2', 'c': '3'}
If I understand your requirements correctly, then you can use the following one-liner.
def list_to_dict(rlist):
return dict(map(lambda s : s.split(':'), rlist))
Example:
>>> list_to_dict(['alpha:1', 'beta:2', 'gamma:3'])
{'alpha': '1', 'beta': '2', 'gamma': '3'}
You might want to strip() the keys and values after splitting in order to trim white-space.
return dict(map(lambda s : map(str.strip, s.split(':')), rlist))
You mention both colons and commas so perhaps you have a string with key/values pairs separated by commas, and with the key and value in turn separated by colons, so:
def list_to_dict(rlist):
return {k.strip():v.strip() for k,v in (pair.split(':') for pair in rlist.split(','))}
>>> list_to_dict('a:1,b:10,c:20')
{'a': '1', 'c': '20', 'b': '10'}
>>> list_to_dict('a:1, b:10, c:20')
{'a': '1', 'c': '20', 'b': '10'}
>>> list_to_dict('a : 1 , b: 10, c:20')
{'a': '1', 'c': '20', 'b': '10'}
This uses a dictionary comprehension iterating over a generator expression to create a dictionary containing the key/value pairs extracted from the string. strip() is called on the keys and values so that whitespace will be handled.

Adding multiple key,value pair using dictionary comprehension

for a list of dictionaries
sample_dict = [
{'a': 'woot', 'b': 'nope', 'c': 'duh', 'd': 'rough', 'e': '1'},
{'a': 'coot', 'b': 'nope', 'c': 'ruh', 'd': 'rough', 'e': '2'},
{'a': 'doot', 'b': 'nope', 'c': 'suh', 'd': 'rough', 'e': '3'},
{'a': 'soot', 'b': 'nope', 'c': 'fuh', 'd': 'rough', 'e': '4'},
{'a': 'toot', 'b': 'nope', 'c': 'cuh', 'd': 'rough', 'e': '1'}
]
How do I make a separate dictionary that contains all the key,value pair that match to a certain key. With list comprehension I created a list of all the key,value pairs like this:
container = [[key,val] for s in sample_dict for key,val in s.iteritems() if key == 'a']
Now the container gave me
[['a', 'woot'], ['a', 'coot'], ['a', 'doot'], ['a', 'soot'], ['a', 'toot']]
Which is all fine... but if I want to do the same with dictionaries, I get only a singe key,value pair. Why does this happen ?
container = {key : val for s in sample_dict for key,val in s.iteritems() if key == 'a'}
The container gives only a single element
{'a': 'toot'}
I want the something like
{'a': ['woot','coot','doot','soot','toot']}
How do I do this with minimal change to the code above ?
You are generating multiple key-value pairs with the same key, and a dictionary will only ever store unique keys.
If you wanted just one key, you'd use a dictionary with a list comprehension:
container = {'a': [s['a'] for s in sample_dict if 'a' in s]}
Note that there is no need to iterate over the nested dictionaries in sample_dict if all you wanted was a specific key; in the above I simply test if the key exists ('a' in s) and extract the value for that key with s['a']. This is much faster than looping over all the keys.
Another option:
filter = lambda arr, x: { x: [ e.get(x) for e in arr] }
So, from here, you can construct the dict based on the original array and the key
filter(sample_dict, 'a')
# {'a': ['woot', 'coot', 'doot', 'soot', 'toot']}

Categories