for loop through a dictionary - python3 - python

I am just trying to make sense of the piece of code below:
names = [{'name': alice}, {'name':bob}, {'name': david}]
with_comma= ', '.join(name['name'] for name in names[:-1])
What is name['name'] there? How does it extract names from the corresponding dictionaries?
Additionally, what I learned from textbooks is we are supposed to write what will happen after every iteration of for loop "AFTER" the for name in names[:-1], and where is it?
I hope I have written clearly. Thanks for the help.

You need to break down the code in smaller parts and understand the smaller parts to understand the whole.
names is a list containing three dictionaries, each of the dictionaries only contains a single key 'name' with a value. Those values are apparently defined in some other part of the code that we're not given, as these values appear to have been assigned to the variables alice, bob and david.
names[:-1] means 'all the elements of names, except the last', so it's effectively [{'name': alice}, {'name': bob}].
name for name in names[:-1] is a generator, which yields the elements of names[:-1] one at a time. So, it yields {'name': alice} first and then {'name': bob}, and then it completes since there is nothing more to yield.
name['name'] tries to index the variable name with the key 'name'. When name has the value {'name': alice}, name['name'] is whatever the value of alice was when the dictionary was defined.
The .join() method of a string takes an iterable as an argument and puts every element from the iterable together in a new string, with a copy of the original string stuck inbetween each element.
So, this piece of code:
alice = 'Alice'
bob = 'Bob'
david = 'Whatever'
names = [{'name': alice}, {'name': bob}, {'name': david}]
with_comma= ', '.join(name['name'] for name in names[:-1])
Results in with_comma having the value 'Alice, Bob'.
If this is code from a Python training though, I would recommend taking another class or course, because it's not doing a very good job of teaching you Python, throwing in complications like these without explaining the basics.

Related

Calling methods and iterating over list

I'm trying to ask for ingredients in a recipe via the input function. I want to store that ingredient in a dictionary, separated by quantity and ingredient. For example, an input of '3 eggs', should yield {'3': 'eggs'}.
The way i do this is with the separate() and convert_to_dict() methods.
I want to ask continuously for the ingredients by means of the input, hence the while True loop.
Basically, i do this via the following code:
ingredients_list = []
def separate(list):
for i in list:
return re.findall(r'[A-Za-z]+|\d+', i)
def convert_to_dict(list):
i = iter(list)
dct = dict(zip(i, i))
return dct
while True:
ingredient = input("Please input your ingredient: ")
ingredients_list.append(ingredient)
print(convert_to_dict(separate(ingredients_list)))
This works fine, but the only problem with it is that when i input another ingredient, the separate() and convert_to_dict() methods only seem to work for the first ingredient in the ingredient list. For example, i firstly input '3 eggs', and then '100 gr of flour', yet it only returns {'3': 'eggs'}. I'm sure there is something i'm missing, but can't figure out where it goes wrong.
I think you've got the idea of your key-value pairs the wrong way around!
Keys are unique. Updating a dictionary with an existing key will just override your value. So if you have 3 eggs, and 3 cups of sugar, how do you envision your data structure capturing this information?
Rather try doing -
{'eggs': 3} # etc.
That should sort out a lot of problems...
But that's all besides the point of your actual bug. You've got a return in your for-loop in the separate function...This causes the function to return the first value encountered in the loop, and that's it. Once a function's reached a return in exist the function and returns to the outer scope.

How to reference a specific part of a dictionary in Python

Alright, so I am trying to create a simple thing that will tell me the showtimes of the movies at the theatre, the names of the movies, and the Rotten Tomatoes score in Python, but I am having a hard time figuring out how to get the meterScore.
actorCount = 0
actors = []
criticCount = 0
critics = []
franchiseCount = 0
franchises = []
movieCount = 3
movies = [{'name': 'Frozen II', 'year': 2019, 'url': '/m/frozen_ii', 'image': 'https://resizing.flixster.com/QZg2MuPQoRlWcWYAwufbQBlv-I0=/fit-in/80x80/v1.bTsxMzIwMzIxODtqOzE4Mjg3OzEyMDA7NTQwOzgxMA', 'meterClass': 'certified_fresh', 'meterScore': 76, 'castItems': [{'name': 'Kristen Bell', 'url': '/celebrity/kristin_bell'}, {'name': 'Idina Menzel', 'url': '/celebrity/idina_menzel'}, {'name': 'Josh Gad', 'url': '/celebrity/josh_gad'}], 'subline': 'Kristen Bell, Idina Menzel, Josh Gad, '}]
tvCount = 0
tvSeries = []
What I am trying to get from that list of data is the meterScore, if you scroll over to the right far enough you can see it. All this data is part of a bigger dictionary, which I named resultOne, but I don't think that matters. I just need some help figuring out how to reference and get the meterScore from the dictionary, so I can print it out, so when I want to see what movies and what rating they got I can just run this program and it will do it for me. I don't really use dictionaries that much, but the library I am using to get the Rotten Tomato data creates it as this very hard to reference dictionary, so any help is appreciated! What I don't get is that if I try to print(resultOne.movies) it says that that is not an attribute or something to that affect, even though when I put it into something that will print out the keys and values, such as I did to get the code above, it clearly shows it is a key. I also tried to print(resultOne.movies[meterScore]), but that didn't work either.
Dictionary values are looked up by their keys using [], not ..
Now, the trick is that the movies key points to a list. So you need to mix two kinds of indexing that both use []: dictionary indexing, which is by key, and list indexing, which is by position in the list (starting at 0).
Ultimately, you want to do this:
score = resultOne['movies'][0]['meterScore']
^ ^ ^
| | |
lookup in outer dict | |
first item in list |
lookup in inner dict
Try this:
movies[0]['meterScore']
# 76
Why don't you try something like this to extract every meterScore from all the movies in the dictionary:
listOfAllMeterScores = [ movie['meterScore'] for movie in movies ]
In that snippet, movies is a list containing a dict. So index the list then index the dict:
movies[0]['meterScore']
If movies might contain more than one item (or zero for that matter), iterate over it instead to get a list of the meterScores:
meter_scores = [movie['meterScore'] for movie in movies]

Iterating through a list of strings and appending a json returned element for each term in the list

Warning this is very very complex. (I'm an idiot and should probably take a break), Its a confusing title but I'll do my best to explain what I'm running into,
I have this code:
test_terms = ['spartan', 'forerunner', 'didact']
test_list = []
for term in test_terms:
search_term = term
search_service = PyMsCognitiveWebSearch('API_Key', search_term,
custom_params={'title': 'name', 'domain': 'url', 'mkt': 'en-usa', 'description': 'url'})
result = search_service.search(limit=3, format='json')
test_list.append(result[term].json)
print(test_list)
This works when its outside of the loop and I run simply this:
search_term = 'spartan'
search_service = PyMsCognitiveWebSearch('API_Key', search_term,
custom_params={'title': 'name', 'domain': 'url', 'mkt': 'en-usa',
'description': 'url'})
result = search_service.search(limit=3, format='json')
test_list.append(result[0].json)
print(test_list)
which gives me:
[{'id': 'https://api.cognitive.microsoft.com/api/v7/#WebPages.0', 'name': 'Obstacle Course Races | Spartan Race', 'url': 'https://www.spartan.com/', 'isFamilyFriendly': True, 'displayUrl': 'https://www.spartan.com', 'snippet': 'Spartan Race is the global leader in obstacle course races, with the right challenge for anyone - from first-time racers to elite athletes.', 'deepLinks': ... etc, for three more results}]
My first instinct wast to do simply for term in range(len(test_terms)):, however this returned a result but instead of the items in the list, I got information on the number 1 through 3.
Next I tried for item, term enumerate(test_terms):
but I got this error:
TypeError: list indices must be integers or slices, not str
Which makes sense, however I'm not sure exactly how to proceed given that the index is a "string" and I've tried enumerating it in two different ways, removing result[term].json and changing it to result.json throws an object error too.
Any help would be great! Also the package specs if it helps.
UPDATE:
result is a web object that is essentially this (via the documentation):
packaged_results = [WebResult(single_result_json) for single_result_json in json_results.get("webPages", {}).get("value", [])]
Link the source code
But its a giant nested list, I wrote it out on a white board, it returns 3 lists consisting of 9 elements, of mixed types, one list and one dictionary. Literally my nightmare.
The way you're using 'term' in your for loop makes 'term' a string (one of ['spartan', 'forerunner', 'didact']). You're looking for an integer to use in "result[term]", so, stick with enumerate, but remember using enumerate the first part of the tuple is the "enumeration" and the second part is the item.
for i, term in enumerate(test_terms):
...
test_list.append(result[i].json)

int object is not subscriptable error and list mutability error

I am new to using functions, so I'm really stuck here with a few errors.
When I run the second function, I am getting a 'int object is not subscriptable error'
and When I run the third function, it is changing the list based on the user input as hoped for, but when the program is run again, it shows that the change is not permanent, the list is the same as before the user input change. (its also putting 'None' at the end.
first of all it looks like you reached a point in which you should learn classes and dictionaries , since a lot of this can be simplified if you do learn them. but if you want to keep using a list of lists to store your data here's a way to fix your second function:
this list comprehension behaves as you expect:
[i[products[0].index(inquiry)] for i in products[1:]]
as you wanted products[1:] is a list of the last 2 items in your products list, it looks like so: [[10,30,15], [300, 400, 500]]
thus when you iterate over this list in the first iteration i will be [10,30,15] and in the second iteration it will be [300,400,500]
but the other list comprehensions below it don't behave as you expect,
when you do products[2] or products[1] you don't create a sub-list of your products list, you just get the list in that position, so when you do:
[i[products[0].index(inquiry)] for i in products[2]]
the list i will go over is [300, 400, 500] meaning in the first iteration i will be just the integer 300
since what you want to do is iterate over a single field you should just not use list comprehension and use products[2] and products[1] directly like so :
def retrieve_info():
inquiry = input('Which product would you like information about?')
if inquiry in products[0]:
inquiry_2 = input('Would you like information about the quantity, price, or both?')
if inquiry_2 == 'both':
print([i[products[0].index(inquiry)] for i in products[1:]])
if inquiry_2 == 'price':
print(products[2][products[0].index(inquiry)])
if inquiry_2 == 'quantity':
print(products[1][products[0].index(inquiry)])
if inquiry_2 not in ['both','price','quantity']:
print('error')
else:
print('product not in inventory system')
as for the data storing function, it seems fine to me, try printing products at the start and end of the function to see if it changes

Alphabetize a List of Multiline Values in Python?

I have a list of names and addresses organized in the following format:
Mr and Mrs Jane Doe
Candycane Lane
Magic Meadows, SC
I have several blocks of data written like this, and I want to be able to alphabetize each block by the last name (Doe, in this case). After doing some digging, the best I can reckon is that I need to make a "List of lists" and then use the last name as a key by which to alphabetize the block. However, given by freshness to python and lack of Google skills, the closest I could find was this. I'm confused as to converting each block to a list and then slicing it; I can't seem to find a way to do this and still be able to alphabetize properly. Any and all guidance is greatly appreciated.
If I understood correctly, what you want basically is to sort values by "some computation done on the value", in this case the extracted last name.
For that, use the key keyword argument to .sort() or sorted():
def my_key_function(original_name):
## do something to extract the last name, for example:
try:
return original_name.split(',')[1].strip()
except IndexError:
return original_name
my_sorted_values = sorted(my_original_values, key=my_key_function)
The only requirement is that your "key" function is deterministic, i.e. always return the same output for each given input.
You might also want to sort by last name and then first name: in this case, just return a tuple (last, first): if last si the same for two given items, first will be used to further sort the two.
Update
For your specific case, this function should do the trick:
def my_key_function(original_name):
return original_name.splitlines()[0].split()[-1]
Assuming you already have the data in a list
l = ['Mr and Mrs Jane Smith\nCandycane Lane\nMagic Meadows, SC',
'Mr and Mrs Jane Doe\nCandycane Lane\nMagic Meadows, SC',
'Mr and Mrs Jane Atkins\nCandycane Lane\nMagic Meadows, SC']
You can specify the key to sort on.
l.sort(key=lambda x: x.split('\n')[0].split(' ')[-1])
In this case, get the last word (.split(' ')[-1]) on the first line (.split('\n')[0])
you want to make a new list where each entry is a tuple containing the sort key you want and the whole thing. Sort that list and then get the second component of each entry in the sort:
def get_sort_name (address):
name, address, city = address.split('\n')
return (name.split(' ')[-1] , address) # last item of first line & whole thing as tulle
keyed_list = map (get_sort_name, addresses)
keyed_list.sort()
sorted_addresses = [item[1] for item in keyed_list]
Thi could be more compact using lambdas of course but its better to be readable :)

Categories

Resources