I'm looking at Spotify music with python. Haven't been able to find an answer online so far. I'd like to get information from each song retrieved from the API (2000 songs). I've got the artist of every song, which is a long string of json seen below:
print(artist):
#This is the output:
[[{'track': {'album': {'artists': [{'external_urls': {'spotify': 'https://open.spotify.com/artist/1uiEZYehlNivdK3iQyAbye'},
'href': 'https://api.spotify.com/v1/artists/1uiEZYehlNivdK3iQyAbye',
'id': '1uiEZYehlNivdK3iQyAbye',
'name': 'Tom Misch',
'type': 'artist',
'uri': 'spotify:artist:1uiEZYehlNivdK3iQyAbye'},
{'external_urls': {'spotify': 'https://open.spotify.com/artist/2rspptKP0lPBdlJJAJHqht'},
'href': 'https://api.spotify.com/v1/artists/2rspptKP0lPBdlJJAJHqht',
'id': '2rspptKP0lPBdlJJAJHqht',
'name': 'Yussef Dayes',
'type': 'artist',
'uri': 'spotify:artist:2rspptKP0lPBdlJJAJHqht'}]}}},
# and so on
Since the artist variable is a list of lists & dictionaries, when I print the length of artist I get 20:
len(artist)
20
However, within each element of the artist variable, there are 100 items:
len(artist[0])
100
I want to loop through all 2000 items in artist, and add them to one list. So far my code has been very clunky:
artist_list = []
i=0
while i<100:
artist_list.append(artist[0][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[1][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[2][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[3][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[4][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[5][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[6][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[7][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[8][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[9][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[10][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[11][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[12][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[13][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[14][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[15][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[16][i]["track"]["album"]["artists"][0]["name"])
artist_list.append(artist[17][i]["track"]["album"]["artists"][0]["name"])
i+=1
What's the best way to shorten this? I've tried using enumerate but couldn't quite figure how to do it. Any help would be much appreciated!
You can achieve this using a double for loop:
artist_list = []
for a in artist:
for b in a:
artist_list.append(b["track"]["album"]["artists"][0]["name"])
However, it's more pythonic (and efficient) to use a python list comprehension:
artist_list = [b["track"]["album"]["artists"][0]["name"] for a in artist for b in a]
Related
def data_change(account):
data_name = data["name"]
data_desc = data["description"]
data_country = data["country"]
return f"{data_name}, is a {data_desc}, from {data_country}"
print(f"option A : {data_change(data_a)}")
The above code is data I want to process for the random data to display.
the list dictionary below are the first 2 example data
data = [
{
'name': 'Instagram',
'follower_count': 346,
'description': 'Social media platform',
'country': 'United States'
},
{
'name': 'Cristiano Ronaldo',
'follower_count': 215,
'description': 'Footballer',
'country': 'Portugal'
}]
and the error display is
TypeError: list indices must be integers or slices, not str
on the line: data_name = data["name"]
yes, I searched for numerous solutions but it didn't get my problem solved.
like from this link
https://www.learndatasci.com/solutions/python-typeerror-list-indices-must-be-integers-or-slices-not-str/#:~:text=This%20type%20error%20occurs%20when,using%20the%20int()%20function.
if u want to want the full file for the code ask me ok. it is a work in progress
Data is a list and not a dictionary so you use zero based index to enumerate the items in the list. You could enumerate the items via a for loop like this:
def data_change(data):
ans = []
for account in data:
data_name = account["name"]
data_desc = account["description"]
data_country = account["country"]
ans.append(f"{data_name}, is a {data_desc}, from {data_country}")
return "\n".join(ans)
Your variable data is a list with two dictionaries in it.
With data_name = data["name"] you try to access this list but name is not an integer, so you get the TypeError.
Your list only has two entries, so you can access it with data[0]["name"] or data[1]["name"].
Edit: Iterating over the dicts in your list as Mazimia stated, seems like a good idea.
I am currently attempting to extract information from the following data set formatted as a list where each news article is its own dictionary:
news_data = [{'source': {'id': 'the-verge', 'name': 'The Verge'}, 'author': 'Emma Roth', 'title': "Judge rules Tesla can't hide behind arbitration in sexual harassment case - The Verge", 'description': 'A lawsuit accusing Tesla of fostering a work environment with “rampant” sexual harassment will continue in court after a judge blocked Tesla’s request for arbitration.', 'url': 'https://www.theverge.com/2022/5/24/23140051/judge-rules-tesla-hide-behind-arbitration-sexual-harassment-case-elon-musk', 'urlToImage': 'https://cdn.vox-cdn.com/thumbor/t3DT8qyznxCW4ahGTwGCSC4l56s=/0x146:2040x1214/fit-in/1200x630/cdn.vox-cdn.com/uploads/chorus_asset/file/10752835/acastro_180430_1777_tesla_0001.jpg', 'publishedAt': '2022-05-24T22:16:03Z', 'content': 'Tesla cant dismiss this case so easily\r\nIllustration by Alex Castro / The Verge\r\nA lawsuit that accuses Tesla of fostering a workplace with rampant sexual harassment will continue in court after a Ca… [+2274 chars]'}, {'source': {'id': 'bloomberg', 'name': 'Bloomberg'}, 'author': None, 'title': 'Elon Musk Drops Out of $200 Billion Club Again as Tesla Tumbles - Bloomberg', 'description': None, 'url': 'https://www.bloomberg.com/tosv2.html?vid=&uuid=38abbf6a-dbe7-11ec-9ad9-767145594c47&url=L25ld3MvYXJ0aWNsZXMvMjAyMi0wNS0yNC9lbG9uLW11c2stZHJvcHMtb3V0LW9mLTIwMC1iaWxsaW9uLWNsdWItYWdhaW4tYXMtdGVzbGEtdHVtYmxlcw==', 'urlToImage': None, 'publishedAt': '2022-05-24T21:11:29Z', 'content': "To continue, please click the box below to let us know you're not a robot."}]
Specifically, I want to extract only the keys 'title' and 'description', saving them into a list for use later.
I've attempted to do this with the following list comprehension:
news_info = [((k,v) for (k,v) in article if k in ['title', 'description']) for article in news_data]
However, if I print the result, I am simply informed:
[<generator object <listcomp>.<genexpr> at 0x102c27840>, <generator object <listcomp>.<genexpr> at 0x102c26dc0>]
Furthermore, if I attempt to access information (e.g. print(news_info[0]['title'])) there is a "TypeError: 'generator' object is not subscriptable".
I was wondering how I can go about printing and accessing/using the information that is saved in the list.
I'm not 100% on the intend, but from what you've tried it seems like you are looking for the result that this should present you:
news_info = [{'title': article['title'], 'description': article['description']} for article in news_data]
print(news_info[0]['title'])
I'd recommend using a function to create the dictionary though.
((k,v) for (k,v) in article if k in ['title', 'description']) - this piece of code creates generator expression. That's why you are getting generator objects.
Another mistake is that you are iterating over dictionary keys, not k,v pairs.
Taking both into account that is what it should look like:
news_info = [(k,v) for article in news_data for (k,v) in article.items() if k in ['title', 'description']]
Your outer () inside the comprehension is creating a generator. If you're expecting a tuple to be created inside here, then just append the word tuple to the beginning.
news_info = [tuple((k,v) for (k,v) in article.items() ...
You also had an issue in that you need to be iterating over the article items.
I'm trying to push data to Firebase and I was able to loop through an array and push the information on each loop.
But I need to add some pictures in this (So it'd be like looping an array inside a dictionary definition). I have all the links in an array.
This is my code so far.
def image_upload():
for i in range(len(excel.name)):
doc_ref = db.collection('plans').document('doc-name').collection('collection-name').document()
doc_id = doc_ref.id
data = {
'bedroomLocation': excel.bedroomLocation[i],
'bedrooms': excel.bedrooms[i],
'brand': excel.brand[i],
'catalog': excel.catalog[i],
'category': excel.category[i],
'code': excel.code[i],
'depth': excel.depth[i],
'description': excel.description[i],
'fullBaths': excel.fullBaths[i],
'garage': excel.garage[i],
'garageBays': excel.garageBays[i],
'garageLocation': excel.garageLocation[i],
'garageType': excel.garageType[i],
'date': firestore.SERVER_TIMESTAMP,
'id': doc_id,
'halfBaths': excel.halfBaths[i],
'laundryLocation': excel.laundryLocation[i],
'name': excel.name[i],
'onCreated': excel.onCreated[i],
'productType': excel.productType[i],
'region': excel.region[i],
'sqf': excel.sqf[i],
'state': excel.state[i],
'stories': excel.stories[i],
'tags': [excel.tags[i]],
'width': excel.width[i],
}
doc_ref.set(data)
That works fine, but I don't really know how to loop through the array of links.
This is what I tried below the block I copied above.
for j in range(len(excel.gallery)):
if len(excel.gallery[j]) != 0:
for k in range(len(excel.gallery[j])):
data['gallery'] = firestore.ArrayUnion(
[{'name': excel.gallery[j][k][0], 'type': excel.gallery[j][k][1],
'url': excel.gallery[j][k][2]}])
print(data)
doc_ref.set(data)
len(excel.gallery) has the same length as len(excel.name)
each j position has different amount of links though.
If I declare the gallery inside the data definition and I use ArrayUnion and pre define more than one piece of information it works fine, but I need to use that array to push information to Firebase.
excel.gallery is a matrix actually, is not a dictionary. And this is one of the example outputs for this [[['Images/CFK_0004-Craftmark_Oakmont_Elevation_1.jpeg', 'Elevation', 'url example from firebase'], .... and it goes on for each file. I'm testing with 8 images and 2 plans. So my matrix is 2x4 in this case. But it can happen that in a position there won't be any files if none match. What I'm looking for is add to the data before it is pushed (or after it doesn't matter the order) all the urls for that plan.
This works:
'gallery': firestore.ArrayUnion(
[{'name': 'Example Name', 'type': 'Elevation',
'url': 'Example url'},
{'name': 'Example Name2', 'type': 'First Floor',
'url': 'Example url2'}])
But I need to populate that field looping through excel.gallery
I'm a little confused by when you say, "I have all the links in an array". Could we see that array and what kind of output you are looking for?
Also assuming that excel.gallery is a dictionary you could clean up your code substantially using the items() function.
for j, k in excel.gallery.items():
if k:
data['gallery'] = firestore.ArrayUnion([{'name': k[0], 'type': k[1], 'url': k[2]}])
print(data)
doc_ref.set(data)
I am new to python, and I am trying to split a list of dictionaries into separate lists of dictionaries based on some condition.
This is how my list looks like this:
[{'username': 'AnastasiadesCY',
'created_at': '2020-12-02 18:58:16',
'id': 1.33421029132062e+18,
'language': 'en',
'contenttype': 'text/plain',
'content': 'Pleased to participate to the international conference in support of the Lebanese people. Cypriot citizens, together with the Government 🇨🇾, have provided significant quantities of material assistance, from the day of the explosion until today.\n\n#Lebanon 🇱🇧'},
{'username': 'AnastasiadesCY',
'created_at': '2020-11-19 18:13:06',
'id': 1.32948788307022e+18,
'language': 'en',
'contenttype': 'text/plain',
'content': '#Cyprus stand ready to support all efforts towards a coordinated approach of vaccination strategies across Europe, that will prove instrumental in our fight against the pandemic.\n\nUnited Against #COVID19 \n\n#EUCO'},...
I would like to split and group all list's elements that have the same username into separate lists of dictionaries. The elements of the list - so each dictionary - are ordered by username.
Is there a way to loop over the dictionaries and append each element to a list until username in "item 1" is equal to username in "item 1 + 1" and so on?
Thank you for your help!
Finding the same thing works the best if we sort the list by it - then all the same names are next to each other.
But even after sorting, we don't need to do such things manually - there are already tools for that. :) - itertools.groupby documentation and a nice explanation how it works
from itertools import groupby
from operator import itemgetter
my_list.sort(key=itemgetter("username"))
result = {}
for username, group in groupby(my_list, key=itemgetter("username")):
result[username] = list(group)
result is a dict with usernames as keys
If you want a list-of-lists, do result = [] and then result.append(list(group)) instead.
A better would be to create a dictionary with username as key and value as list of user attributes
op = defauldict(list)
for user_dic in list_of_userdictss:
op[user_dic.pop('username')].append(user_dic)
op = OrderedDict(sorted(user_dic.items()))
list of dict to separate lists
data = pd.DataFrame(your_list_of_dict)
username_list = data.username.values.tolist()
I have a list of dicts and need to filter on the 'name' key (values are guaranteed to be unique) in the nested dict in order to return a single dict.
I have a working solution but thought there would be more efficient/elegant/pythonic methods.
I tried dictionary comprehension but couldn't get my head around how it would iterate over the list
Solutions for for 2.7+ and 3 would be appreciated.
companies=[
{
'c01': {
'name':'x',
'address': '1 st'
}
},
{
'c02': {
'name':'y',
'address': '2 st'
}
},
]
company = [ c for c in companies if c.values() == [ v for v in c.values() if v['name']=='x'] ][0]
print company
Output:
{'c01': {'name': 'x', 'address': '1 st'}}
Something like this. For loops can be enhanced though
company_dict = {}
for company in companies:
for c in company:
company_dict[c] = company.get(c)
print (company_dict)
I am always a fan of making things more readable than trying to play code golf -
- although thats fun sometimes too :)
That being said, we can simply iterate through each element in your companies and look for the target name, then we return that company's info:
def get_target_company_info(companies):
TARGET_NAME = 'loans'
for company in companies:
company_id = company.keys()[0]
name_val = company.get(company_id).get('name')
if name_val == TARGET_NAME:
return company
return None
company = get_target_company_info(companies)
print company
output:
{'c01': {'name': 'loans', 'address': '1 st'}}
To be a bit closer to what you wanted exactly, we can provide a filtering util method and filter as such:
method:
TARGET_NAME = 'loans'
def is_relevant_company(company):
company_id = company.keys()[0]
name_val = company.get(company_id).get('name')
return company if name_val == TARGET_NAME else None
filter:
relevant_companies = filter(None, [is_relevant_company(company) for company in companies])
output:
[{'c01': {'name': 'loans', 'address': '1 st'}}]
Try this:
[c for c in companies if any(['name' in c[x] and c[x]['name']=='x' for x in c])]
this filters out all companies with name == "x" and the output for your example will be:
[
{'c01': {'name': 'x', 'address': '1 st'}}
]
You just want one dictionary, so there is not need for a list comprehension. Just iterate over the companies using a loop and break when you find your match (assuming your data structure is identical for each item in the list).
target = 'loans'
result = {}
for company in companies:
data = company.values()[0] # There is only one name & address per company record.
if data['name'] == target: # Check if the company name matches the target.
result = data # If so, set the result to the data for the target company.
break # Then break from the loop, as you've found the only match.
For python 3, you need to make the following modification:
data = list(company.values())[0]
def find_company_with_name(name):
return next(c for c in companies if c.values()[0]['name'] == name)
Using a generator expression is more efficient than a list comprehension, since it can stop searching once it finds a match without generating the rest of the list.