shorter way to delete key from a dictionary - python

I have wanted to delete the taste key from the line_items dict list of the entire dictionary list. the code is given below
orders = [
{
'order_id' : 1,
'line_items': [
{
'product_id': 2,
'product_name' : 'mango',
'taste' : 'sweet',
},
{
'product_id':3,
'product_name': 'grape',
'taste': 'sweet & sour',
}
],
},
{
'order_id' : 2,
'line_items': [
{
'product_id': 4,
'product_name' : 'lime',
'taste' : 'sour',
}
]
},
]
I have already done it. and this is my solution.
delitems = ['taste']
for order in orders:
for item in order["line_items"]:
for delkeys in delitems:
item.pop(delkeys)
But I think it is a bad code and wanted to know if is there any way to shorting my code
with dict comprehension or another way?

Slightly more natural than using dict.pop when you don't care about the value you're deleting would be to use the del statement:
del item[delkeys]
Obviously, this doesn't reduce the number of lines. If you're only ever deleting the one key, you don't need the delitems and the loop over it. If you don't mind hard-coding that "taste" is the key to delete, just do:
for order in orders:
for item in order["line_items"]:
del item["taste"]
While you could write a bunch of nested list comprehension and dictionary comprehensions to achieve the same effect in a single statement, it would be a lot harder to understand than your simple nested loop code.

for order in orders:
for item in order["line_items"]:
del item["taste"]

Related

Create dictionary comprehension using multiple lists

I am a newbie in python.
I have 3 lists (price_list/address_list/link_list), I am trying to combine them in one dictionary with this structure:
{
{
"price":price,
"address":address,
"link":link,
},
{
"price":price,
"address":address,
"link":link,
}
}
I am able to create the list with nested dictionaries but not dictionary with nested dictionary
my_dict = [{'price': price, 'address': address, 'link': link} for price, address, link in zip(price_list, address_list, link_list)]
What would be the equivalent please?
A dictionary is essentially a data structure that maps certain values to a collection of keys. Your inner dictionary seems to be fine. You have defined a key and a value. However, in your outer dictionary, you seem to be only having list of values (the inner dicts) and no key to associate them with.
For instance, I have added 'key1' and 'key2' to demonstrate that your outer dictionary needs to have keys defined.
{
"key1": {
"price":price,
"address":address,
"link":link,
},
"key2": {
"price":price,
"address":address,
"link":link,
}
}
So what you're asking is not exactly possible.
However, if you manage to find some keys for your outer dictionary, then you can iterate over the list of dicts that you already have and then assign the elements of the list against some key in the outer dict.
Something like this should work if you're looking for a one-liner:
my_dict = {i: j for i,j in zip(range(len(price_list)), [{'price': price, 'address': address, 'link': link} for price, address, link in zip(price_list, address_list, link_list)])}
It would return:
{
0: {'price': price1, 'address': 'addr1', 'link': 'link1'},
1: {'price': price2, 'address': 'addr2', 'link': 'link2'},
2: {'price': price3, 'address': 'addr3', 'link': 'link3'}
}
Unlike List, Dictionary is like a JSON object, i.e. always has a key-value pair. So you must specify a key, like this:
myDict = {
"dict1":{ // Key
"price":price, // Values
"address":address,
"link":link,
},
"dict2":{ // Key
"price":price, // Values
"address":address,
"link":link,
}
}
Assuming all three lists you have are of the same length, you can do this to get a nested dictionary:
myDict = {}
for i in range(len(price_list)): // You can use any other list instead.
myDict[i] = { // Or whatever key suites you.
"price": price_list[i]
"address": addess_list[i]
"link": link_list[i]
}
You cannot create a Dictionary with nested Dictionaries like you created one with the list.
This is due to the fact that every element in a dictionary must have a key.
If you want to create a nested dictionary then the outermost dictionary (containing dictionaries) must have keys for every dictionary.
{
1 :{
"price":price,
"address":address,
"link":link,
},
2 :{
"price":price,
"address":address,
"link":link,
}
}
Something like this where 1, 2 are keys.
to do this simply initialize a variable with 1
then after adding values increment the variable
for eg
in loop()
i = 1
dic = {}
dic[i] = "whatever"
i += 1

How to sort dictionary with keys, using certain field in dict - Python 3

second try for this question. I already changed 2 suggested answers, but they didn't solved my problem.
My dictionary looks like this:
old_list = {
"x": {
"bd_date": "04/01/1977",
"name": "Deli Mirko",
"next": "04/02/2021",
"renew": 1,
"type": "birthday",
"until": 335
},
"y": {
"bd_date": "25/11/1983",
"name": "Deli Marina",
"next": "25/11/2021",
"renew": 1,
"type": "birthday",
"until": 295
},
.....
}
I wish to sort it using "until" values ASC.
Is there a way to do this.
I tried suggested solutions,
Sort nested dictionary by values
Sort nested dictionary by value, and remainder by another value, in Python
but I don't get result OR it changes my dictionary format. I need to keep format, because the rest of code.
I tried
new_list = sorted(old_list.items(), key=lambda i: i[1]['until'])
but it changes format to list from dict - [("x",{...}), ("y",{..})...]
So, how to change above code to keep format {"x": {...}, "y": {...}}
This is important because later in code I use loop that outputs data
events_keys = old_list.keys()
for events_key in events_keys:
event = old_list[events_key]
# Get values for each event
tmp_bd = event['bd_date']
tmp_name = event['name']
....
so I guess I need to sort dict first, so printed values come in increasing order?!
Just use dictionary comprehension on your sort result. This works since from Python 3.6 onwards, the standard dict type maintains insertion order by default.
new_list = {k:v for k, v in sorted(old_list.items(), key=lambda i: i[1]['until'])}
new_list:
{'y': {'bd_date': '25/11/1983',
'name': 'Deli Marina',
'next': '25/11/2021',
'renew': 1,
'type': 'birthday',
'until': 295},
'x': {'bd_date': '04/01/1977',
'name': 'Deli Mirko',
'next': '04/02/2021',
'renew': 1,
'type': 'birthday',
'until': 335}}

Counter for occurrences of element of one dictionary in another dictionary in python

I have a list of nested dictionaries that all have another list of dictionaries inside that I am interested in. That is, if I have:
list_of_dicts[0]['data_i_need']
it contains the following dictionary:
[
{
'key1': ['item1', 'item2', 'item3'],
'details': 'details'
},
{
'key2': ['item2', 'item4'],
'details': 'other details'
}
]
I have another large dictionary (d2) that has the following structure:
{
'item1': {
'details': ['detail1', 'detail2',],
'classes': ['class2'],
},
'item2': {
'details': ['detail1'],
'classes': ['class1', 'class2'],
},
}
I would like to add another dictionary to every dictionary in list_of_dicts that would be the following:
{'class1': 2, 'class2': 3}
I.e. if an item is corresponding to a class is in the list_of_dicts[0]['data_i_need'], I would need to count it. I want to loop through every dictionary in list_of_dicts.
I have tried many things, among which is something like the below, but I feel stuck now.
import Counter
for l in list_of_dict:
for d in l['data_i_need']:
Counter(d2[d]["classes"])
You should always define full inputs and full outputs for code you want to implement; this question doesn't specify exact input and exact output you desire, it tries to vaguely explain it. It's really hard to process the question as posed: you should provide semantic value and you should provide exact values. "classes" means nothing without context; "item1" and "key1" means nothing. "details" is also meaning-free as-is. Providing specifics eases reading of the question and allows readers to help out beyond just "how do I implement this puzzle": you want good answers and solutions, not answers to a puzzle.
If I am understanding correctly, you want to iterate over all the dictionaries in the first list and update this dict based on some other criteria. Let's just separate this by passing both to a new function -- doable because python dicts are passed by reference:
for d in list_of_dicts:
add_class_counts(d, itemInfo)
(I'm renaming d2 into itemInfo because it has at least a bit more semantic information.)
I'm assuming d is going to be a single dictionary consisting of:
{
'data_i_need': [
{
'key1': ['item1', 'item2', 'item3'],
'details': 'some irrelevant details',
},
{
'key2': [...],
# more?
}
]
}
I am confused that you have key1 and key2. Shall we assume it's just items? You should turn key1 and key2 from keys into a value under a key name, e.g.:
{
'name': 'key1',
'items': ['item1', 'item2']
'details': 'some irrelevant details'
}
The problem is, if the input is not structured like this, how do you know which key1 and key2 are these magical key names? You need an allowlist of other constant keys like details, which you would then ignore trying to guess which of the other keys is key1:
def name_for_datadict(d):
# note: untested code.
allow_list = ['details']
all_keys = d.keys()
unknown_keys = [k for k in all_keys if k not in allow_list]
if len(unknown_keys) == 1:
return unknown_keys[0]
# if it's 0 or greater than 1, we couldn't guess, give up
raise Exception('invalid data: ' + str(d))
This is ugly and will (intentionally) break if you have more than one 'non-constant' key.
Let's now try to understand what should add_class_counts() do. It seems like you want to specify how many items in the list are part of a certain class.
Let's see; add_class_counts() needs to go through every item in the passed dict:
def add_class_counts(d, itemInfo):
# expected input:
# d = {
# 'name': 'key1',
# 'items': ['item1', 'item2'],
# }
class_counts = {}
for itm in d['items']:
class_list = classes_for_item(itmName, itemInfo):
# TODO: count it somehow
How do we know which classes is an item a part of? It's obvious, really:
def class_list(itmName, itemInfo):
# this should return ['class1', 'class2']
return itemInfo[itemName]['classes']
How do we count this?
def add_class_counts(d, itemInfo):
class_counts = {}
for itm in d['items']:
class_list = classes_for_item(itmName, itemInfo):
for class_name in class_list:
try:
class_counts[class_name] += 1
except: # TODO: limit to the 'key not found' exception which I cannot remember right now
class_counts[class_name] = 0
# we've finished counting.
# update the existing dictionary with the counts.
d['class_counts'] = class_counts
Note: the code is untested, and it's doing weird things (maybe you want to return class_counts and then update d?). But it might give you a basic idea.
Of course, if it's not implementing what you expected, you will really want to write a much more concrete, semantically-rich explanation of what the inputs are and what you want to receive as an output. Anyone that's genuinely trying to help will want to understand why you're trying to do what you're trying to do.

Looping through Dictionary Transforms Type to List

I have a simple dictionary in python. For each item in the dictionary, I have another dictionary I need to attach to each line (i.e. 5 contacts, each contact has FirstName, LastName, Gender, plus 'other' fields which all fall in single embedded dictionary.
I have attached the loop I am using. The resulting output is exactly how I want it, but when I run a type() function on it, Python reads it as a list rather than a dictionary. How can I convert it back to a dictionary?
itemcount = 0
for item in dict_primarydata:
dict_primarydata[itemcount]['otherData'] = dict_otherdata[itemcount]
itemcount = itemcount+1
I'm going to hazard a guess and say dict_primarydata and dict_otherdata look something like this to start out:
dict_primarydata = [
{
'first_name': 'Kaylee',
'last_name': 'Smith',
'gender': 'f'
},
{
'first_name': 'Kevin',
'last_name': 'Hoyt',
'gender': 'm'
}
]
dict_otherdata = [
{
'note': 'Note about kaylee'
},
{
'note': 'Note about kevin'
}
]
It looks like dict_primarydata and dict_otherdata are initialized as lists of dicts. In other words, dict_primarydata is not actually a dict; it's a list containing several dicts.
If you want your output to be a dict containing dicts you need to perform a conversion. Before you can do the conversion, you need to decide what you will use as key to your outer dict.
Sidenote
Since you are iterating over two lists. A range-based for loop would be a bit more readable:
for i in range(len(dict_primarydata)):
dict_primarydata[i]['otherData'] = dict_otherdata[i]

How to add a key,value pair to a list?

I would like to be able to create a list of key, list pairs ( I think that's the most accurate way to describe my desired solution...)
I have a list of dictionaries and would like to add an element to each of these dictionaries that is a list of dictionaries (a mouthful, I know...).
To do this, I try to append key, value pairs to a list. When I do this I get a syntax error ostensibly tripped on the colon in the key:value pair.
Here's my code:
d_l[0]['abilities'] = list()
d_l[0]['abilities'].append(abilities_m_l[job_row]['Element Name']:list()) # ability: stats about ability
where d_l is a list of dictionaries, 'abilities' is a key that I am creating.
And here's my error (the caret is on the colon (although in the past it's mislabeled the location of the error)).
d_l[0]['abilities'].append(abilities_m_l[job_row]['Element Name']:list()) # ability: stats about ability
^
SyntaxError: invalid syntax
logout
If it helps, this is the desired overall structure:
{
'job':'clerk', 'description': 'works in a bank', 'abilities': [
'math': [
'imp': {
'Data Value': 4.5,
'N' : 8,
'S_E': 0.19
},
'level': {
'Data Value': 4.75,
'N': 8,
'S_E': 0.25
}
],
'english': [
'imp': {
},
'level': {
}
],
'dexterity': [
'imp':{
},
'level': {
}
]
]
},
Thanks so much! If you see obvious flaws in my arrangement just above (maybe I should be using a dictionary for abilities instead of a list?) please let me know.
You want to append a dict - note the {}, eg:
.append( {abilities_m_l[job_row]['Element Name']:list()} )
And it's more Pythonic and efficient to use [] for an empty list...

Categories