How to map the dict it contains two values? - python

I am not able to match the dict values with dict keys because for some dict contains two values.
my_dict = {
'Incident':'INC, Incident',
'Minor Enchancement':'Change',
'ServiceRequest':'SR, ServiceRequest'
}
input:
new_list= ['Incident','Inc','SR','Change']
output:
new_list = ['Incident','Incident','Minor Enchancement','Service Request']
i want read the list and match with dictionary . some key contains two values in the dictionary how can we match dict ?

Here is a better organization:
xlate = {
'INC': 'Incident',
'Inc': 'Incident',
'Change': 'Minor Enhancement',
'SR': 'ServiceRequest'
}
words = ['Incident','Inc','SR','Change']
new_list = []
for w in words:
new_list.append( xlate.get(w, w) )
print(new_list)
Output:
['Incident', 'Incident', 'ServiceRequest', 'Minor Enhancement']
Note that I use .get(w,w) which will pass "not found" entries through unchanged.

You want to invert the keys and values in the original dictionary, and split the values to produce multiple keys:
my_dict = {
'Incident':'INC, Incident, Inc', #note that I added another alias
'Minor Enchancement':'Change',
'ServiceRequest':'SR, ServiceRequest'
}
reversed_dict = {}
for key in my_dict:
items = [x.strip() for x in my_dict[key].split()]
for i in items:
reversed_dict[i] = key
assert reversed_dict['Incident'] == 'Incident'
assert reversed_dict['Inc'] == 'Incident'
Note that there is no 'magic' way to navigate between using Inc and INC, so if you want to be able to handle either case you need to include them as options.

Related

Get a dictionary having a specific key value pair from a complex dictionary

I hit a specific scenario where I want to get the dictionary which contains specific value out of a complex dictionary.
For example consider the below dictionary
a = {"tire1": {"source": "PEP","dest": "host1"},"tire6":{"source": "REP","dest":"host2"}}
If the value of dest host1 matches then the function should return {"tire1": {"source": "PEP","dest": "host1"} of type dictionary.
EDIT: If it matches multiple same values then it should returns multiple matching dictionary in a single dictionary
Thanks
You Can do something like this by using dictionary comprehension
final_dict = {key: value for key,value in a.items() if value["dest"] == "host1" }
You could define a function with a results list, iterate on the keys and values of dictionary a, append to the results list any values (sub-dictionaries) where the 'dest' key equals 'host1', and then return the list of results.
def func(a: dict):
results = [] # define a list of results to return
for key, value in a.items(): # iterate on keys values
if value['dest'] == 'host1':
results.append(a[key]) # append that sub-dict to the results
return results
This would return:
result = func(a)
print(results)
----
{
"tire1":
{
"source": "PEP",
"dest": "host1"
}
}
You can simply write a loop to match the specified value.
In your case, the code is following:
dicts = {"tire1": {"source": "PEP","dest": "host1"},"tire6":{"source": "REP","dest":"host2"}}
search_value = 'host1'
for key, values in dicts.items():
for value in values.values():
if value == search_value:
print(f'The Key is {key} and', f'The dictionary are {values}')
This will return the matched dictionary with the key. The result will be:
The Key is tire1 and The dictionary are {'source': 'PEP', 'dest': 'host1'}
A more robust option could be:
a = {"tire1": {"source": "PEP", "dest": "host1"},
"tire6": {"source": "REP", "dest": "host2"}}
result = {k: v for k, v in a.items() if v.get('dest') == 'host1'}
print(result)
...in case there are sub-dictionaries where the 'dest' key is absent

What would be the best way to go about converting this list of data to dictionary

I have a rough idea of how I can do this but unsure where to start implementing. Looking for tips and advice please.
I want to convert data 1, key value tuple pairs, into data 2, a dictionary.
Data 1:
[
('category0[title]', 'dinner'),
('category0[items][][name]', 'chicken'),
('category0[items][][name]', 'steak'),
('category0[items][][price]', '19'),
('category0[items][][price]', '79'),
('category0[items][][description]', 'oven roasted chicken'),
('category0[items][][description]', 'wagyu steak and fries'),
('category1[title]', 'dessert'),
('category1[items][][name]', 'cookies'),
('category1[items][][price]', '3'),
('category1[items][][description]', 'chocolate chip')
]
Data 2
[
{
'category-title': 'dinner',
'items': [
{
'item-name': 'chicken',
'item-price': '19',
'item-description': 'oven roasted chicken'
},
{
'item-name': 'steak',
'item-price': '79',
'item-description': 'wagyu steak and fries'
},
]
},
{
'category-title': 'dessert',
'items': [
{
'item-name': 'cookies',
'item-price': '3',
'item-description': 'chocolate chip'
},
]
}
]
Constraints:
For there to be another dictionary in the list, there must be another category title entered
The only variable is the number of items, but each item will have a name, price, and description
When trying to transform data from one format to another it's best to take it in steps so that it's easier to follow.
How I look at it is that each part of the string is a attribute to access the object and that the first part of the string is unique and so it can be used as a key. So I did the transform in three steps.
Convert the string to a tuple containing the key and the individual parts and the value. So ('category0[items][][name]', 'chicken') turns into ('category0', 'items', '', 'name', 'chicken')
Using the categoryX as a key, create a dict to hold the tuples for that specific key. ('category0', 'items', '', 'name', 'chicken') becomes dict['category0'].append(('items', '', 'name', 'chicken')). Making sure to add a check to see if the key is already in the dict or not to avoid overwriting data or getting KeyError.
Using that dict convert the tuple to dict that is returned and added to a list to contain all items.
# Convert the string of "category0[items][][name]" to a list of attributes so we can work with it easier.
def split_attrs_to_list(item_list: list[tuple[str, str]]) -> list[tuple[str]]:
attr_value_list = []
for attr_value in item_list:
# Split by '[' and then replace ']' with an empty string to remove all brackets and have a list of attributes
attributes = tuple(_str.replace(']', '') for _str in attr_value[0].split('[')) + (attr_value[1],)
attr_value_list.append(attributes)
return attr_value_list
# Using the first part of the attributes as a key we can find distinct item from the list and add them to a dict
def distinct_items_by_key(attrs_value_list: list[tuple[str]]) -> dict[str, list[tuple[str]]]:
attrs_value_dict = dict()
for attrs_value in attrs_value_list:
key = attrs_value[0]
if key not in attrs_value_dict:
attrs_value_dict[key] = list()
attrs_value_dict[key].append(attrs_value[1:])
return attrs_value_dict
# Parse the list of attributes, build a dict and add the attributes and values to the dict
def parse(attrs_value: list[tuple[str]]):
obj = dict()
title = attrs_value[0][1]
items = []
item_tuples = attrs_value[1:]
# Since there is only 3 attributes for a given "item" we can divide by 3 and know exactly how many items there are
item_count = len(item_tuples) // 3
# Use offsets to grab that appropriate value
for i in range(item_count):
item_name = item_tuples[i * 3][-1]
item_price = item_tuples[i * 3 + 1][-1]
item_description = item_tuples[i * 3 + 2][-1]
items.append({'item-name': item_name, 'item-price': item_price, 'item-description': item_description})
obj['category-title'] = title
obj['items'] = items
return obj
def convert_to_dict(item_list: list[tuple[str, str]]):
attrs_value_list = split_attrs_to_list(item_list)
distinct_items = distinct_items_by_key(attrs_value_list)
parsed_items = [parse(item) for item in distinct_items.values()]
# Add code here to use parsed_items
convert_to_dict(input_list)

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)

Getting the key from a value within a dict of dicts

I have a dict of dicts dict_of_dicts={1:{'id':1,'name':'joe'},2: {'id':2,'name':'jim'},3: {'id':3,'name':'bob'}} (the structure is out of my control so I cannot define my dict more conveniently). I am looking to extract the id # (which also corresponds to the key of the upper dict) of the sub dict containing 'name':'bob'. i.e I want to extract the id value for a specific name.
I have thought of a looping solution, but is there a more pythonic way to go about this? My attempt is below
for i in list(dict_of_dicts.values()):
if i['name']=='bob':
print(i['id'])
Here is solution you can try out,
search_ = 'bob'
for k, v in dict_of_dicts.items():
if search_ in v.values():
print(f"Id {k}")
break
else:
print("No Match Found")
Edit
def search_(key):
for k, v in dict_of_dicts.items():
if key in v.values():
return k
return -1 # Indicating no match found
for k, v in dict_of_dicts.items():
if v["name"] == "bob":
print(v["id"])
You can also just print(k)
Even if the structure is out of your control, in case you want to have multiple searches, it might make sense to reformat the data before searchign multiple times, you can match the results later again if needed:
d = {1:{'id':1,'name':'joe'},2: {'id':2,'name':'jim'},3: {'id':3,'name':'bob'}}
n = {e['name']:e['id'] for e in d.values()}
n.get('bob')
#Out[32]: 3
Alternatively you could use filter function by passing a lambda that resolves to True if the name matches the search criteria. I passed in a default value of {'id': None} when grabbing the first item using next item if there are no match.
filtered = filter(lambda x: x['name'] == 'bob', dict_of_dicts.values())
match = next(filtered, {'id': None})
print(match['id'])
A one-liner:
d={1:{'id':1,'name':'joe'},2: {'id':2,'name':'jim'},3: {'id':3,'name':'bob'}}
print ([ k for k,v in d.items() if 'bob' in v['name'] ])
Output:
[3]
Here you get a list of keys/id in case you have multiple ids with `'name':'bob'.
You can use next() to find the first instance in a generator that satisfy your needs:
dict_of_dicts = {
1: {
'id': 1,
'name': 'joe'
},
2: {
'id': 2,
'name': 'jim'
},
3: {
'id': 3,
'name': 'bob'
}
}
# Find "bob"
try:
id_bob = next(
dict_of_dicts[key]["id"]
for key in dict_of_dicts
if dict_of_dicts[key]["name"] == "bob"
)
except StopIteration:
print("'bob' not found, handle this some way")
raise
# bob_id == 3
If you know for sure that "id" is the same value as the key, just use key instead of dict_of_dicts[key]["id"].

Using dict keys in python as values in a different dict

I would like to create a "translator" type of dict that would assign values that are keys in different dicts, which are nested, to keys in a dict that I created. The problem I run into is that I can't create a value that represents a nested dict key without having to convert that to a string or some other data type, and when I try to use a string as an index to the nested dict, I get an index error. Ideally, my dict would look something like this:
new_dict{
"new_key_1" : ['subdict1']['subdict2']['old_key_1'],
"new_key_2" : ['subdict1']['subdict2']['old_key_2'],
"new_key_3" : ['subdict1']['subdict3']['old_key_3']
}
Then, for each nested dict, I could generate a new dict object with a simple for loop:
for key, value in new_dict.items() :
user_dict_1[key] = OldDict[value]
The nested dicts are very large and I only need a few fields from each, otherwise I could just use the .copy() function to work with the old dicts.
PS- Any help in rewriting this question to be more readable also appreciated.
You're going to need reduce() for this one...
attrmap = {
"new_key_1": ('subdict1', 'subdict2', 'old_key_1'),
...
}
print reduce(lambda x, y: x[y], attrmap[somekey], old_object)
Are you talking something like this?
from pprint import pprint as pp
subdict1 = {'subdict1_item1':1, 'subdict1_item2':2}
subdict2 = {'subdict2_item1':3, 'subdict2_item2':4}
subdict3 = {'subdict3_item1': 5, 'subdict3_item1':6}
olddict = {
'old_key_1': [subdict1, subdict2],
'old_key_2': [subdict1, subdict2],
'old_key_3': [subdict1, subdict3],
}
newdict = {
'new_key_1': olddict['old_key_1'].append('old_key_1'),
'new_key_2': olddict['old_key_2'].append('old_key_2'),
'new_key_3': olddict['old_key_3'].append('old_key_3'),
}
or this
newdict = {
'new_key_1': 'old_key_1',
'new_key_2': 'old_key_2',
'new_key_3': 'old_key_3',
}
def getnew(newkey, newdict, olddict):
if newkey in newdict:
oldkey = newdict[newkey]
if oldkey in olddict:
preitem = olddict[ oldkey ] # returns a list with two items
item = []
item.append([preitem[0]]) # makes subdict1 wrapped in a list
item.append([preitem[1]]) # makes subdict2/3 wrapped in a list
item.append([oldkey])
return item
else:
raise KeyError('newdict has no matching olddict key')
results to:
pp( getnew('new_key_1', newdict, olddict) )
print
pp( getnew('new_key_2', newdict, olddict) )
print
pp( getnew('new_key_3', newdict, olddict) )
[[{'subdict1_item1': 1, 'subdict1_item2': 2}],
[{'subdict2_item1': 3, 'subdict2_item2': 4}],
['old_key_1']]
[[{'subdict1_item1': 1, 'subdict1_item2': 2}],
[{'subdict2_item1': 3, 'subdict2_item2': 4}],
['old_key_2']]
[[{'subdict1_item1': 1, 'subdict1_item2': 2}],
[{'subdict3_item1': 6}],
['old_key_3']]

Categories

Resources