Best way to substitute both K&V based on a map? - python

Let say we have a map-dict and data-dict :
m = { 1:2, 4:5, 3:7 }
data = { 1:7, 4:1, 3:6 }
we should replace all occurrences both key&val in "data" according to "m" :
data1 = { 2:7, 5:2, 7:6 }
what is the shortest, fast way to do this ?
I was thinking of converting data to list do the replacements and convert back to dict. But even that gets too involved.
Converting list to dict is OK :
dict(zip(lst[0::2], lst[1::2]))
Converting dict to list is :
data.items()
but this one does not return list, but list of tuples, which make things too involved i.e we need to additionally flatten this LoT.
I was wondering if there is a better way, with emphasis on speed/mem.

dict comprehension:
data1 = {m.get(k, k): m.get(v, v) for k, v in data.items()}
Note that {4: 1, 4: 6} in your example is a single element.

Related

Find item in list of dicts

I have a list of dictionary something like this:
list = [
{
"ENT_AUT":[
"2018-11-27"
]
},
{
"ENT_NAT_REF_COD":"C87193"
},
{
"ENT_NAM":"MONEYBASE LIMITED"
},
{
"ENT_NAM_COM":"MONEYBASE LIMITED"
},
{
"ENT_ADD":"Ewropa Business Centre, Triq Dun Karm"
},
{
"ENT_TOW_CIT_RES":"Birkirkara"
},
{
"ENT_POS_COD":"BKR 9034"
},
{
"ENT_COU_RES":"MT"
}
]
Here every dictionary will always contain only one key value pair. Now I need to know the value of ENT_NAM, ENT_AUT and etc all fields.
I tried something like this:
ENT_NAM = (list[2].values())[0]
print('ENT_NAM = ', ENT_NAM)
It works perfectly for this list but my problem is that the 'ENT_NAM' containing dictionary will not always be on the 2nd index of the list. How can I generalize this solution so that even if the order of the dictionary under the list changes, I always find a perfect solution?
What you are describing is a search problem. Here the naive solution is probably fine:
def get_prop(dicts, k):
return next(x[k] for x in dicts if k in x)
get_prop(l, "ENT_NAM")
Incidentally, don't call your variable list: it shadows a builtin.
If you need to use this data more than about 3 times I would just reduce it to a dict:
def flatten(dicts):
iterdicts = iter(dicts)
start = next(iterdicts)
for d in iterdicts:
start.update(d)
return start
one_dict = flatten(list_of_dicts)
one_dict["ENT_NAM"]
(There are plenty of other ways to flatten a list of dicts, I just currently think the use of iter() to get a consumable list is neat.)
As jasonharper said in the comments, if it is possible, the data should be formulated as a single dictionary.
If this cannot happen, you can retrieve the value of ENT_NAM using:
print(list(filter(lambda elem: "ENT_NAM" in elem.keys(), my_list))[0]["ENT_NAM"])
Returns:
MONEYBASE LIMITED
Note: list has been renamed to my_list since list is a reserved Python keyword
If all of the keys are unique, you can flatten the list of dictionaries into a dictionary with a straightforward dictionary comprehension.
Note: you don't want to use list as a name for a variable, as it is an important built-in type. Use something like lst instead.
{ k: v for d in lst for k, v in d.items() }
Result:
{'ENT_AUT': ['2018-11-27'], 'ENT_NAT_REF_COD': 'C87193',
'ENT_NAM': 'MONEYBASE LIMITED', 'ENT_NAM_COM': 'MONEYBASE LIMITED',
'ENT_ADD': 'Ewropa Business Centre, Triq Dun Karm',
'ENT_TOW_CIT_RES': 'Birkirkara', 'ENT_POS_COD': 'BKR 9034',
'ENT_COU_RES': 'MT'}
Getting the value for key 'ENT_NAM' is now just:
{ k: v for d in lst for k, v in d.items() }['ENT_NAM']

How to get flattened list of all inner level nested keys in dictionary - python?

I'm trying to get a list of all keys in the nested level of my dictionary.
My dictionary resembles:
my_dict= {
'DICT':{
'level_1a':{
'level_2a':{}
},
'level_1b': {
'level_2b':{},
'level_2c':{}
}
}
My desired output should resemble:
['level_2a', 'level_2b', 'level_2c']
What I've tried:
[list(v) for k, v in json['DICT'].items()]
My current output:
[['level_2a'], ['level_2b', 'level_2c']]
I want my result to be fully flattened to a single-level list. I've tried flattening libraries but the result tends to appear as: ['level_2a', 'level_2blevel_2c'] which is incorrect. Not looking to make the code more complex by creating another method just to flatten this list.
Would appreciate some help, thank you!
Try:
my_dict = {
"DICT": {
"level_1a": {"level_2a": {}},
"level_1b": {"level_2b": {}, "level_2c": {}},
}
}
lst = [vv for v in my_dict["DICT"].values() for vv in v]
print(lst)
Prints:
['level_2a', 'level_2b', 'level_2c']

Best way to merge elements of a dictionary python

I am facing a problem where I have to merger different elements of a dictionary based on some condition. What is the most pythonic way to achieve that?
For example , I have the below dictionary
dict = {
'a': [element1 , element2]
'b': [element2, element3]
'c': [element4, element5, element1]
'd': []
}
My resulting dictionary should be
dict = {
'a': [element1, element2, element3, element4, element5]
}
What would be the best way to achieve that?
I want to merge them based upon condition which is evaluated by is_compatible method. So lets' say I will merge two elements if this function returns true
Is there a way I can do this?
result = {
'a': list(set().union(*input_dict.values()))
}
I don't clearly get what you want to do, but it seems like you want to combine all lists as a set. You can do something like this:
new_list = []
for element in dict.values():
for value in element:
new_list.append(element)
new_list = list(set(new_list))
new_dict = {
dict.keys[0]: new_list
}
Hope this helps!

How can I convert a list of dict keyx:valuex to a list dict key:keyx, value:valuex?

So I have a list like this:
[
{ '1234' : 'Sun'}
{ '353453' : 'Earth'}
...
]
I want to convert this to
[
{ 'temp': '1234', 'planet' : 'Sun'}
{ 'temp': '353453', 'planet': 'Earth'}
...
]
What's the Pythonic way to have this list of dict converted?
You can use a nested list/dictionary comprehension:
lst = [
{ '1234' : 'Sun'},
{ '353453' : 'Earth'}
]
out = [ { 'temp': k, 'planet': v } for l in lst for k, v in l.items() ]
# [{'temp': '1234', 'planet': 'Sun'}, {'temp': '353453', 'planet': 'Earth'}]
You shouldn’t try to do it in a one liner, it wouldn't be readable. You should construct the output list for each element one by one.
The fellow that will read your code later (and this might be yourself in a couple of month) will thank you.
You can do something like
a = [{'1234': 'Sun', "12": "mars"}]
output = []
for measurement in a:
output_list_of_dict = [{"temp": temp, "planet": planet} for temp, planet in measurement.items()]
output.extend(output_list_of_dict)
Note that in each loop turn, the result is a list itself : one dictionary may contain several temperatures. Therefore I used «extend» method, which merges the lists, and not append.
Doing it in an explicit and readable way conforms to the python philosophy.
It is the most pythonic in this sense.
Out of my head I would write something like below:
>>> l = [{ '1234' : 'Sun'}, { '353453' : 'Earth'}]
>>> r = [{'temp':list(x.keys())[0], 'planet': x[list(x.keys())[0]]} for x in l if len(x) == 1]
The core issue is that this will only work with a correctly formed input data structure, and this is not guaranteed in any way by the input format. Hencefore a prior validation of input data may be useful.
But if I had to put that kind of thing in production code, I would certainly avoid oneliner as suggested by #François-Dailloux and write instead the stupid and simple code below, which is also very readable and also likely faster:
l = [{ '1234' : 'Sun'}, { '353453' : 'Earth'}]
res = []
for d in l:
if len(d) == 1:
for k, v in d.items():
res.append('temp': k, 'planet': v)
If the len is not as expected I would also of course raise some exception to avoid propagation of broken input data.

convert the value of dictionary from list to float

I have a dictionary named "location" like this:
{
'WA': [
'47.3917',
'-121.5708'
],
'VA': [
'37.7680',
'-78.2057'
],
...
}
I want to convert to a dic that the value is a float, so it looks like:
{
'WA': [
47.3917,
-121.5708
],
'VA': [
37.7680,
-78.2057
],
...
}
I tried
for key in location.keys():
location[key] = float(location[key][0,1])
print location
it gives me an arror that "float() argument must be a string or a number"
how can I fix that?
You can use dictionary comprehension to construct a dictionary which has the values converted to floats, like this
print {k:map(float, locations[k]) for k in locations}
As suggested by #Grijesh in the comments section, if you are using Python 3,
print({k:list(map(float, locations[k])) for k in locations})
Your problem is in here: float(location[key][0,1])
# float objects are length 1
for key in location.keys():
location[key] = [float(location[key][0]),float(location[key][1])]
print location
You can use a list comprehension within a dictionary comprehension. Since you need both keys and values, use dict.items to iterate key-value pairs:
res = {k: [float(x) for x in v] for k, v in locations.items()}
map works more efficiently with built-ins, so you may wish to use:
res = {k: list(map(float, v)) for k, v in locations.items()}
Or, since you have coordinates, for tuple values:
res = {k: tuple(map(float, v)) for k, v in locations.items()}
The problem with your logic location[key][0,1] is Python lists do not support vectorised indexing, so you need to be explicit, e.g. the verbose [float(location[key][0]), float(location[key][1])].

Categories

Resources