Find item in list of dicts - python

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

Related

Collect sub-elements in a json object python

So essentially I have a JSON object obtained through an API that looks similar to the one below and I am wondering how I would collect the sub-elements such as name and quantity and place it into an array/list.
{
"item_one": {
"name": "Item One",
"weight": 0,
"quantity": 1
},
"item_two": {
"name": "Item Two",
"weight": 0,
"quantity": 23
},
"item_three": {
"name": "Item Three",
"weight": 0,
"quantity": 53
}
}
An example for what the desired output is would be the following:
nameLst = ['Item One', 'Item Two', 'Item Three']
quantityLst = ['1', '23', '53']
So far the only way I know how to do this would be to individually collect the quantity and name data by searching through all the specific items, this however would be impossible due to the sheer number of potential items.
You don't need to know the item names, you can simply loop over the keys of the dictionary and use those keys to query the JSON blob for each subdict.
namelst = []
quantitylst = []
for key in d.keys():
subdict = d[key]
namelst.append(subdict["name"])
quantitylst.append(subdict["quantity"])
If you don't need the keys at any point, then you can loop over the values solely as Kelly Bundy mentions.
for v in d.values():
namelst.append(v["name"])
quantitylst.append(v["quantity"])
So far the only way I know how to do this would be to individually collect the quantity and name data by searching through all the specific items, this however would be impossible due to the sheer number of potential items.
I imagine you're just saying that this would be hard to do by hand, and you could do something like this.
distinct_keys = {k for d in json_obj.values() for k in d}
# you seem to want to convert ints to strings?
# if so, consider (some_transform(d[k]) if k in d else None)
result = {k:[d.get(k, None) for d in json_obj.values()] for k in distinct_keys}
If you actually need to iterate through this thing one object at a time though, consider something like the following:
from collections import defaultdict
result = defaultdict(list)
for d in json_obj.values():
# if you KNOW you don't have missing data
# for k,v in d.items(): result[k].append(v)
# you probably do have missing data though, so a cost proportional
# to your key sizes is unavoidable starting from completely unprocessed
# json data. you could save a little work, but here's the basic idea
# the work we do is different based on which sets/maps have they
# keys we're operating on
s = set(d.keys())
new_keys = s.difference(result)
missing_keys = [k for k in result if k not in s]
same_keys = s.intersection(result)
# this doesn't necessarily have to be special cased, but it
# allows us to guarantee result is non-empty everywhere else
# and avoid some more special casing.
if new_keys and not result:
for k,v in d.items():
result[k].append(v)
else:
# backfill new keys we found with None
L = result[next(iter(result))]
for key in new_keys:
result[key] = [None]*len(L)
result[key].append(d[key])
# fill in None for the current object for any keys in result
# that we don't have available
for key in missing_keys:
result[key].append(None)
# for everything in both objects, just append the new data
for key in same_keys:
result[key].append(d[key])
Then if you really needed variables and not a dictionary you can explicitly store them that way.
for k,L in result.items():
globals()[f'{k}Lst'] = L

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

Python - Pull Out Values from Only Dictionaries that Meet a Certain Criteria

I have a Python list called "results" that has dictionaries as its values:
results = [
{
'postingStatus': 'Active',
'postEndDate': '1601683199000',
'boardId': '_internal',
'postStartDate': '1591084714000)'
},
{
'postingStatus': 'Expired',
'postEndDate': '1601683199000',
'boardId': '_external',
'postStartDate': '1591084719000)'
}
]
How would I create a list that gets all the values from the dictionary where the 'boardID' value is '_internal' (but ignores the dictionary where 'boardID' is '_external')? As an end result, I'm hoping for a list with the following contents:
['Active','1601683199000','_internal','1591084714000']
You can use list-comprehension:
out = [v for d in results for v in d.values() if d["boardId"] == "_internal"]
print(out)
Prints:
['Active', '1601683199000', '_internal', '1591084714000)']
without using List-comprehension
for items in results:
if items['boardId'] == '_internal':
lst1 = list(items.values())
print(lst1)

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

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.

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