I have a nested dictionary containing both the title and the number of pages of a book. I want to write a function that gets as first argument the dictionary to search in and as second one a page number (as string). The function will then search through the dictionary and print all the titles of book which have the same number of pages as in the second argument.
Here's an example of my dictionary:
text = {
1: {
1: {"ch.name": "The Boy Who Lived", "pages": "146"},
2: {"ch.name": "The Vanishing Glass", "pages": "126"},
},
2: {
1: {"ch.name": "The Worst Birthday", "pages": "129"},
2: {"ch.name": "Dobby's Warning", "pages": "125"},
},
}
I have tried the following:
def Name(text,pages):
pages=pages
for key1, value1 in text.items():
for key2, value2 in value1.items():
output = key1,key2,value2['ch.name'],value2['pages']
output
if pages is pages:
print(f"{value2['ch.name']}")
Name(text, '125')
The result is:
The Boy Who Lived
The Vanishing Glass
The Worst Birthday
Dobby's Warning
However, the result had to the following, because it is the only book with exactly 125 pages:
Dobby's Warning
CodePudding user response:
You may want to use dict.values()
instead of dict.items()
at times when the key doesn't matter. This will likely reduce some confusion later down the line.
Given:
text = {
1: {1: {'ch.name': 'The Boy Who Lived', 'pages': '146'},
2: {'ch.name': 'The Vanishing Glass', 'pages': '126'}},
2: {1: {'ch.name': 'The Worst Birthday', 'pages': '129'},
2: {'ch.name': "Dobby's Warning", 'pages': '125'}}
}
Doing:
# This could easily be translated to the nested for-loops you have~
out = [y['ch.name'] for x in text.values() for y in x.values() if y['pages'] == '125']
for x in out:
print(x)
Output:
Dobby's Warning
CodePudding user response:
I don't really understand what you're trying to do. You create an output variable, but you don't use it variable to check whether to page numbers correspond. Instead, you use the expression if pages is pages
, which always evaluates to True because you're comparing the same object. Also, the line pages=pages
has no effect.
I have reworked your code to the following:
def Name(text,pages):
for key1, value1 in text.items():
for key2, value2 in value1.items():
output = key1,key2,value2['ch.name'],value2['pages']
if output[3] == pages:
print(f"{value2['ch.name']}")
I have replaced the always-true if pages is pages
with if output[3] == pages
. Now, we are actually compared the value in the dictionary, which is put in the output variable, with the argument pages
. I've also removed the second and the sixth line, because they did not do anything usefull.
But if you want to, you can further simplify it by taking the value directly out of the value2 dictionary. The output variable then becomes useless:
def Name(text,pages):
for key1, value1 in text.items():
for key2, value2 in value1.items():
if value2['pages'] == pages:
print(f"{value2['ch.name']}")
Do also note that I've used the ==
operator instead of the is
operator. The is
operator does only check for identity. Thus, it does only evaluate to True when the two compared objects are the same object. It won't evaluate to True when you are passing in two different objects with the same value. (Actually, for strings this isn't completely true, see this page for more information) The ==
operator on the other hand will only check for equality. It will this compare the value of the objects and evaluate to True when they are the same and False otherwise. It doesn't care about whether the objects are the same or not. For that reason, the ==
is almost always preferred.
CodePudding user response:
The same approach as BeRT2me's, just in few lines instead of 1:
def Name(text, pages):
for dct in text.values():
for dct_2 in dct.values():
if str(pages) in dct_2.values():
print(dct_2["ch.name"])
Name(text, 125)
#
# Result: Dobby's Warning