For loop on a dictionary giving out of range error - python

I'm having troubles understanding dictionaries and for loop.
I have this example that takes a nested dictionary representing a playlist of songs. On the first example the code runs just fine, but when I try to create a function and try to clean up the code. It keeps saying index out of range. Can anybody throw their 2 cents.
Example playlist from a JSON file:
playlist = {
'title': 'faves',
' author': 'Me',
'songs': [
{
'title': 'song1',
'artist': ['john', 'smith'],
'genre': 'Pop',
'duration' : 3.23
},
{
'title': 'song2',
'artist': ['john2'],
'genre': 'Rock',
'duration' : 3.45
},
{
'title': 'song3',
'artist': ['john3', 'smith3'],
'genre': 'Jazz',
'duration' : 2.45
}
]
}
This first code byte works well and print the right strings.
sa = f" and {song['artist'][1]}"
for song in playlist['songs']:
print(f"{song['title']} by {song['artist'][0]}{sa if len(song['artist']) >= 2 else ''}, runtime: {song['duration']}, genre: {song['genre']}")
song1 by john and smith3, runtime: 3.23, genre: Pop
song2 by john2, runtime: 3.45, genre: Rock
song3 by john3 and smith3, runtime: 2.45, genre: Jazz
But here when I try to run this it says index out of range. It's calling artist_two, but is not supposed to do that unless there is more than one artist for a song.
def print_playlist(songs):
print(songs)
for song in songs:
title = song['title']
duration = song['duration']
genre = song['genre']
artists = song['artist']
artist_one = song['artist'][0]
artist_two = song['artist'][1]
sa = f" and {artist_two}"
print(f"{title} by {artist_one}{sa if len(artists) >=2 else ''}, runtime: {duration}, genre: {genre}")
print_playlist(playlist['songs'])

You can use this method to make a string of the names with " and " in between them.
artist_list=["John","Smith"]
y=" and ".join(str(x) for x in artist_list)
print(y)
This give the output of John and Smith
And if you make the artist list: ["John","Smith","Dave"]
Your output will look like John and Smith and Dave
As mentioned in the comment above, you are assuming there are always at least 2 elements in the artist_list. You should rather use an approach like mine that I found from Concatenate item in list to strings

Thank you Zack Tarr
final code looks like
def print_playlist(songs):
for song in songs:
title = song['title']
duration = song['duration']
genre = song['genre']
artists = song['artist']
artist_plus = " and ".join( artist for artist in artists)
print(f" {title} by {artist_plus if len(artists) >= 2 else artists[0]}, runtime: {duration}, genre: {genre}")
print_playlist(playlist['songs'])

Related

Using a list as an index for another list python

I am trying to create an online shopping cart system in python to understand list better but have come across some struggles.
I am having difficulties with displaying information using a list. I have already created a list where the person writes in the product the code into an empty list as shown below.
else:
code_input.append(i)
quan_input.append(s)
code_inputed.append(code_input)
quan_inputed.append(quan_input)
I want to use the list with the product codes to find the correlating name and price by using trying to use the code_input list as an index to find the items in the other list.
I have written the simple code to try to find if it works but it comes up with TypeError: list indices must be integers or slices, not list
The code
def display():
index = code_inputed
for i in code_inputed: # and index in range(len(productList)):
print(index)
print(productList[index], quan_inputed[index])
Any help would be greatly appreciated and I'm sorry if none of this makes any sense I am only new.
Thank you
It is a bit unclear what you want, but do you perhaps mean:
def display():
index = code_inputed
for i in code_inputed: # and index in range(len(productList)):
print(i) #CHANGED TO i!
print(productList[i], quan_inputed[i])
Incorporate this code based on your needs. But you get the idea on how to do that. I made list of dicts using 3 lists you provided (productList, priceList, code_of_product) And everything else is just straight forward :)
productList = ["Salad Server Set", "Party Serviette Holder", "Tea Set", "Mixing Bowl Set", "Knife Block Set",
"Coffee Capsule Holder", "Plastic Sensor Soap Pump", "Storage Bucket", "Oven Glove", "Apron",
"Biscuit Barrel", "Chopping Board", "Carioca Cups", "Soup Bowls", "Elevate Wood Turner",
"Pasta Machine", "Teapot", "Cake Pop Scoop", "Cookbook Stand", "Chocolate Station", "Coffee Maker",
"Pepper Mill", "Salt Mill", "Glass Storage Jar", "Measuring jug", "Kitchen Scale", "Tenderiser",
"Pizza Docker", "Knife Sharpener", "Steel Cork Opener", "Steel Garlic Press", "Steel Can Opener",
"Stainless Steel Crank Flour Sifter", "Mineral Stone Mortar and Pestle", "Citrus Cather",
"Cherry & Olive Pitter", "Multi Grater-Detachable", "Stainless Steel Colander", "Steel Pizza Pan",
"Pop Container"]
priceList = [18.70, 11.95, 39.95, 49.95, 99.95, 29.95, 79.95, 24.95, 9.95, 29.95, 39.95, 12.95, 54.95,
43.00, 19.95, 144.95, 29.95, 9.95, 29.95, 34.95, 29.00, 84.94, 84.95, 4.95, 19.95, 39.95, 34.95,
19.95, 79.95, 36.95, 34.95, 36.95, 33.95, 74.95, 19.95, 27.95, 26.95, 44.95, 12.95, 22.95];
code_of_product = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,
38,39]
# Generate a list of dicts from 3 lists productList, priceList, code_of_product
products = [ {'product_name': productList[i], 'price': priceList[i], 'code': code_of_product[i] } for i in range(len(productList)) ]
def catalogue():
global productList, priceList, code_of_product
print('{:<12}\t{:<40}{:<20}'.format("code", "product", "Price $"))
print('{:<12}\t{:<40}{:<20}'.format("----", "------------------------------------", "-------"))
for prod in range(len(products)):
print('{:<12}\t{:<40}{:<20}'.format(products[prod]["code"], products[prod]["product_name"], products[prod]["price"]))
catalogue()
code = int(input("Please input code?"))
quantity = int(input("Please input quntity?"))
def showRecord(cd, qty):
price = products[cd]["price"]
total = float(price)*float(qty)
print(f"Product name: {products[cd]['product_name']}")
print(f"Price: ${price}")
print(f"Total: {total}")
showRecord(code, quantity)

How do I add a list of brand names to data frame or if it does not appear add 'None'?

brand_names = ["Tommy Hilfiger", "Tommy Jeans", "Hugo", "Hugo Boss", "Boss", "HUGO", "Lacoste", "lacoste",
"Adidas",
"adidas", "Armani", "The North Face", "Paul Smith", "Vivienne Westwood", "Levis", "Kent And Curwen",
"Nike", "BOSS", "Calvin Klein", "Kent and Curwen",
"Pretty Green", "Lyle And Scott", "Moschino", "Converse", "Timberland", "Ralph Lauren", "Fred Perry",
"True Religion",
"Luke 1977", "Belstaff", "Paul And Shark", "CP Company", "Money Tri Wheel", "Money Sig", "Gant","Versace"]
image = []
title = []
price = []
link = []
shop = []
brand = []
mainline_t_shirt(soup, brand_names)
mainline = pd.DataFrame({
'Images': image,
'Titles': title,
'Prices': price,
'link': link,
'Website': 'mainlinemenswear',
'brand': brand
})
# Image
(code) 63 elements- code working
# Title
(code) 63 elements- code working
# Price
(code) 63 elements- code working
# link
(code) 63 elements- code working
# website
(code) 63 elements- code working
#brand
**for container5 in title_div:
for temp in brand_names_in:
if temp in container5.text:
print(temp)
brand.append(temp)
if temp not in container5.text:
brand.append("None")**
The data frame 'mainline' has 63 rows. The issue is the 'brand' column. Everytime I run this code I get this error
raise ValueError("arrays must all be same length")
ValueError: arrays must all be same length
This is because not all the brands(Nike, Adidas etc) are in the container.text. How can I add the string "None" to the row instead of adding the brand?
The code that needs to be changed is in between the two stars.
The problem is that for each container5, you're looping over all your brands. Out of the 20 or so brands, only one (if any) will be matched with container5.text. Every other brand will mismatch and as a result, brand.append("None") is executed. In total about 20 × len(title_div). Which makes the brand list far too large, with lots of "None"s (which you could see if you print(brand) somewhere inside or directly after the loop).
You can use a for-else here:
for container5 in title_div:
for temp in brand_names_in:
if temp in container5.text:
brand.append(temp)
break
else: # not broken out of the inner for-loop, thus there was no match
brand.append("None")

how can i get yaml format with input in python ??(without using pyyaml library)

I want to get data from input that is in yaml format.The data includes user information and music albums information that each user has purchased.Input information is as follows:
2 # this line specify the number of users
- name: user1
age: 18
city: city1
albums:
- album1
- album2
- album3
- name: user2
age: 20
city: city2
albums:
- album2
- album1
- alubm3
3 # this line specify the number of albums
- name: album1
singer: singer1
genre: classic
tracks: 10
- name: album2
singer: singer2
genre: pop
tracks: 22
- name: album3
singer: singer3
genre: pop
tracks: 14
I wrote the following code for this
num_user = int(input())
users_data = {}
albums_data = {}
for i in range(num_user):
name, age, city = input().split()[-1], input().split()[-1], input().split()[-1]
input()
albums=[]
next_line = input()
while next_line.split()[0]=='-' and len(next_line)-len(next_line.lstrip(' '))==4:
albums.append(next_line.split()[-1])
next_line = input()
if len(next_line.split()) < 2:
num_albums = int(next_line)
users_data[name]=[age, city, albums]
for i in range(num_albums):
name, singer, genre, tracks = input().split()[-1],input().split()[-1],\
input().split()[-1], input().split()[-1]
albums_data[name]=[singer, genre, tracks]
Everything is in order until the number of users exceeds one person and I have trouble storing the second user information in the dictionary and all the moving information is stored.
I want this:
{'user1': ['18', 'city1', ['album1', 'album2', 'album3']], 'user2': ['20', 'city2', ['album2', 'album1', 'alubm3']]} {'album1': ['singer1', 'classic', '10'], 'album2': ['beeptunes', 'pop', '22'], 'tekunbede': ['beeptunes', 'pop', '14']}
but get this:
{'user1': ['18', 'city1', ['album1', 'album2', 'album3']], '20': ['city2', 'albums:', ['album1', 'alubm3']]} {'album1': ['singer1', 'classic', '10'], 'album2': ['beeptunes', 'pop', '22'], 'tekunbede': ['beeptunes', 'pop', '14']}
The issue seems to be that once you have processed the last album for the first user you are then calling input() again which is getting the name. Decoupling the input from the processing will help to fix the issue so have a look at creating a function to process a name once its been detected.
so try:
read the input
work out what do based on the input
process the read data
num_user = int(input())
users_data = {}
albums_data = {}
for i in range(num_user):
name, age, city = input().split()[-1], input().split()[-1], input().split()[-1]
input()
albums=[]
next_line = input()
while next_line.split()[0]=='-' and len(next_line)-len(next_line.lstrip(' '))==4:
albums.append(next_line.split()[-1])
next_line = input() # This is the line with the issue
if len(next_line.split()) < 2:
num_albums = int(next_line)
users_data[name]=[age, city, albums]
for i in range(num_albums):
name, singer, genre, tracks = input().split()[-1],input().split()[-1],\
input().split()[-1], input().split()[-1]
albums_data[name]=[singer, genre, tracks]

Why isn't this if statement returning True?

I'm making a program that counts how many times a band has played a song from a webpage of all their setlists. I have grabbed the webpage and converted all the songs played into one big list so all I wanted to do was see if the song name was in the list and add to a counter but it isn't working and I can't seem to figure out why.
I've tried using the count function instead and that didn't work
sugaree_counter = 0
link = 'https://www.cs.cmu.edu/~mleone/gdead/dead-sets/' + year + '/' + month+ '-' + day + '-' + year + '.txt'
page = requests.get(link)
page_text = page.text
page_list = [page_text.split('\n')]
print(page_list)
This code returns the list:
[['Winterland Arena, San Francisco, CA (1/2/72)', '', "Truckin'", 'Sugaree',
'Mr. Charlie', 'Beat it on Down the Line', 'Loser', 'Jack Straw',
'Chinatown Shuffle', 'Your Love At Home', 'Tennessee Jed', 'El Paso',
'You Win Again', 'Big Railroad Blues', 'Mexicali Blues',
'Playing in the Band', 'Next Time You See Me', 'Brown Eyed Women',
'Casey Jones', '', "Good Lovin'", 'China Cat Sunflower', 'I Know You Rider',
"Good Lovin'", 'Ramble On Rose', 'Sugar Magnolia', 'Not Fade Away',
"Goin' Down the Road Feeling Bad", 'Not Fade Away', '',
'One More Saturday Night', '', '']]
But when I do:
sugaree_counter = int(sugaree_counter)
if 'Sugaree' in page_list:
sugaree_counter += 1
print(str(sugaree_counter))
It will always be zero.
It should add 1 to that because 'Sugaree' is in that list
Your page_list is a list of lists, so you need two for loops to get the pages, you need to do
for page in page_list:
for item in page:
sugaree_counter += 1
Use sum() and list expressions:
sugaree_counter = sum([page.count('Sugaree') for page in page_list])

'print key_1 + value_1+value_2 + good ' by using two dictionaries ?? nothing else

dic = {
'key_1':['val_1','val_2'],
'key_2':['val_3','val_4'],
'key_3':['val_5','val_6']
}
info = {
'i_1':'good',
'i_2':'bad'
}
for k,v in dic.items()
print 'Jack scrd'+info[i_2]+"in both subjects"+dic[val1]+'&'+dic[val2]
I know the print code is not right but gave it here for understanding what I really wanted to do here. I want only the above similar line in printing command.
The following does this. The format command allows you to easily substitute {} with the variables of your choice in a string. When it comes to the dictionary dic[k] would render all the lists which ['val_1','val_2'] is one. So you would give dic[k][0] to get the first value, and dic[k][1] to get the second value.
for k,v in dic.items():
msg = 'Jack scrd {} in both subjects {} & {}'
print msg.format(info['i_2'], dic[k][0], dic[k][1])
# Jack scrd bad in both subjects val_1 & val_2
# Jack scrd bad in both subjects val_5 & val_6
# Jack scrd bad in both subjects val_3 & val_4
Perhaps you want to do this?
Remove the for loop
print 'Jack scrd'+info['i_2']+'in both subjects'+str(dic['key_1'][0])+"&"+str(dic['key_1'][1])
you can use .join to join all list items with a given separator. If you want to print all keys of dic you can use:
dic = {
'key_1':['val_1','val_2'],
'key_2':['val_3','val_4'],
'key_3':['val_5','val_6']
}
info = {
'i_1':'good',
'i_2':'bad'
}
for keys in dic:
# .join will join all list items for a particular key with & and store it in variable subjects
subjects = ' & '.join(dic[keys])
print "jack scored " + info['i_1'] + " in both subjects " + subjects
output:
jack scored good in both subjects val_1 & val_2
jack scored good in both subjects val_5 & val_6
jack scored good in both subjects val_3 & val_4
place_iraq = {
'shrine_1' : ['karbala','imam hussein as.'],
'shrine_2' : ['najaf', 'imam ali as.'],
'yard' : ['karbala', 'wadi-us-salam'],
'shrine_3' : ['karbala', 'abbas as.']
}
type = {
't1':'shrine',
't2': 'grave yard'
}
print 'The '+str(type['t1'])+' of '+str(place_iraq['shrine_1'][1])+' is situated in ' +\
str(place_iraq['shrine_1'][0])
print 'The '+str(type['t1'])+' of '+str(place_iraq['shrine_2'][1])+' is situated in ' +\
str(place_iraq['shrine_2'][0])
print 'The '+str(type['t1'])+' of '+str(place_iraq['shrine_3'][1])+' is situated in ' +\
str(place_iraq['shrine_3'][0])
print 'The '+str(type['t2'])+' of '+str(place_iraq['yard'][1])+' is situated in ' +\
str(place_iraq['yard'][0])

Categories