I have a question to how match between dictionaries
I send 3 request to youtube api
first to search
second to video
third to channel
What I try to create is dic that have
Title of the video
Thumbnails of the video
and the profile of the channel that make the video.
here you can see the code and the requests I send:
def get(self,request):
search_url = "https://www.googleapis.com/youtube/v3/search"
video_url = "https://www.googleapis.com/youtube/v3/videos"
channel_url = "https://www.googleapis.com/youtube/v3/channels?part=snippet&id='+commaSeperatedList+'&fields=items(id%2Csnippet%2Fthumbnails)&key={}".format(settings.YOUTUBE_DATA_API_KEY)
para_search = {
'part': 'snippet',
'q': 'Learn Python' ,
'key': settings.YOUTUBE_DATA_API_KEY,
'maxResults': 3,
'type': 'video'
}
search_response = requests.get(search_url,params=para_search)
print(search_response.text)
results = search_response.json()['items']
ids =[]
for result in results:
ids.append(result['id']['videoId'])
para_videos = {
'part': 'snippet',
'key': settings.YOUTUBE_DATA_API_KEY,
'id':','.join(ids),
}
video_response = requests.get(video_url, params=para_videos)
print(video_response.text)
results = video_response.json()['items']
dict_youtube = {}
list_youtube = []
channelIdList = []
for result in results:
dict_youtube = {
'title': result['snippet']['title'],
'thumbnails': result['snippet']['thumbnails']['high']['url'],
'channelId': result['snippet']["channelId"],
}
channelIdList.append(result['snippet']["channelId"])
list_youtube.append(dict_youtube)
param_channel = {
'part':'snippet,contentDetails,statistics',
'key':settings.YOUTUBE_DATA_API_KEY,
'id':','.join(channelIdList)
}
channel_response = requests.get(channel_url,params=param_channel)
print(channel_response.text)
results = channel_response.json()['items']
profile = []
profile_dic = {}
for result in results:
profile_dic = {
'channelId': result['id'],
'profile': result['snippet']['thumbnails']['default']['url'],
}
profile.append(profile_dic)
print(profile)
print(list_youtube)
Input:
profile = [{'channelId': 'UC8butISFwT-*******', 'profile': 'https://yt3.ggpht.com/ytc/A*******ifQn-nYNfkgLvVPkw=s88-********-no-rj'}, {'channelId': 'UCWv7*******mDpPBA', 'profile': 'https://yt3.ggpht.com/tBEPr-zTNXEeae7VZK******2PXSwzMBKVR7W0MI7gyND8=s88-c-k-c0x00ffffff-no-rj'}]
list_youtube = [{'title': 'Learn Python - Full Course for Beginners [Tutorial]', 'thumbnails': 'https://i.ytimg.com/vi/rf****bw/hqdefault.jpg', 'channelId': 'UC******wT-Wl7EV0hUK0BQ'}, {'title': 'Python for Beginners - Learn Python in 1 Hour', 'thumbnails': 'https://i.ytimg.com/vi/kqt*****8/hqd****t.jpg', 'channelId': 'UCWv7*********pPBA'}, {'title': 'Python Tutorial - Python Full Course for Beginners', 'thumbnails': 'https://i.ytimg.com/vi/_uQrJ0TkZlc/hqdefault.jpg', 'channelId': 'U********PBA'}]
As you can see, I've created two lists, each with dictionaries.
And every dictionary has a common key I created and it is channelId
What I want to do is union between dictionaries having the same value in the channelId key, the first list has fewer dictionaries than the second list.
How do I combine the two lists and dictionaries so that everything is compatible
That eventually I will have a list with dictionaries that has the key
'title':
'thumbnails':
'channelId':
'profile':
something like that for example:
[{'title':.... , 'thumbnails':... , 'channelId':... , 'profile':... ,} , { ... }, ...]
That sounds like the classical join operation. You can use a filter to identify the elements that match by id and then update the dictionary with its values like so.
This assumes you have at most 1 video per profile. You might need to flip the variables/add logic depending on their relation
for dic in profile:
vids = filter(lambda yt: yt["channelId"] == dic["channelId"], list_youtube)
for vid in vids:
dic.update(vid)
return dic
Related
I have the following list of dictionaries:
datalist = [
{'Business': 'Business A', 'Category': 'IT', 'Title': 'IT Manager'},
{'Business': 'Business A', 'Category': 'Sourcing', 'Title': 'Sourcing Manager'}
]
I would like to upload to DynamoDB in the following format:
table.put_item(Item={
'Business':'Business A would go here',
'Category':'IT would go here',
'Title':'IT Manager would go here'
},
{
'Business':'Business B would go here',
'Category':'Sourcing would go here',
'Title':'Sourcing Manager would go here'
}
)
I've tried converting the list of dicts to dict first and accessing the elements that way or trying to iterate through the Items parameter but no luck. Any help would be appreciated.
Here's my DynamoDB structure, 3 columns (Business, Category, Title):
{
"Business": {
"S": "Business goes here"
},
"Category": {
"S": "Category goes here"
},
"Title": {
"S": "Title goes here"
}
}
The put_item API call allows you to upload exactly one item, you're trying to upload two at the same time, this doesn't work.
You can batch multiple put items requests using boto3 to decrease the number of API calls. Here's an example adapted from the documentation:
with table.batch_writer() as batch:
for item in datalist:
batch.put_item(
Item=item
)
This will automatically create the batch writes under the hood.
I have a problem I would like to loop inside Stripe to create dynamic multiple objects in checkout. I can not do that after stripe.checkout.Session.create() because I get an error. Also I can not create JSON object in for loop out of stripe.checkout.Session.create(). Any ideas? How can I use for loop and create multiple line_items?
def create_checkout_session(request):
if request.method == "GET":
try:
cart = Cart.objects.get(order_user=request.user)
checkout_session = stripe.checkout.Session.create(
payment_method_types=['card', 'p24'],
line_items=[{
'price_data': {
'currency': 'eur',
'product_data': {
'name': 'total'
},
'unit_amount': cart.total,
},
'quantity': 1,
}],
You should be able to iterate to prepare line_items according to your needs then pass the prepared array:
count = 5
lineItems = []
for i in range(count):
lineItems.append({...})
checkout_session = stripe.checkout.Session.create(
line_items=**lineItems**,
...
)
Let's say I have a list of elements
tagsList = ['dun', 'dai', 'che']
How do I convert the above into the following?
tagsDictionaries = [
{
'name': 'dun'
},
{
'name': 'dai'
},
{
'name': 'che'
}
]
I want to do this with a for loop
tagsDictionaries = [{'name': item} for item in tagsList]
Something like this would work for a flat dictionary. It needs unique key values each time:
for tag in tagsList:
tagDictionary.update({tag + 'uniquekey': tag})
What you show in your example would be a list of dictionaries which can be accomplished as follows:
for tag in tagsList:
tagListDict.append({'name': tag})
Here is a basic for loop that will get you the output that you are seeking:
tagsList = ['dun', 'dai', 'che']
tagsDictionaries = []
for name in tagsList:
new_dict = {'name': name}
tagsDictionaries.append(new_dict)
print(tagsDictionaries)
Here is your output:
[{'name': 'dun'}, {'name': 'dai'}, {'name': 'che'}]
I have a method where I build a table for multiple items for Google's DLP inspect API which can take either a ContentItem, or a table of values
Here is how the request is constructed:
def redact_text(text_list):
dlp = google.cloud.dlp.DlpServiceClient()
project = 'my-project'
parent = dlp.project_path(project)
items = build_item_table(text_list)
info_types = [{'name': 'EMAIL_ADDRESS'}, {'name': 'PHONE_NUMBER'}]
inspect_config = {
'min_likelihood': "LIKELIHOOD_UNSPECIFIED",
'include_quote': True,
'info_types': info_types
}
response = dlp.inspect_content(parent, inspect_config, items)
return response
def build_item_table(text_list):
rows = []
for item in text_list:
row = {"values": [{"stringValue": item}]}
rows.append(row)
table = {"table": {"headers": [{"name": "something"}], "rows": rows}}
return table
When I run this I get back the error ValueError: Protocol message Value has no "stringValue" field. Even though the this example and the docs say otherwise.
Is there something off in how I build the request?
Edit: Here's the output from build_item_table
{
'table':
{
'headers':
[
{'name': 'value'}
],
'rows':
[
{
'values':
[
{
'stringValue': 'My name is Jenny and my number is (555) 867-5309, you can also email me at anemail#gmail.com, another email you can reach me at is email#email.com. '
}
]
},
{
'values':
[
{
'stringValue': 'Jimbob Doe (555) 111-1233, that one place down the road some_email#yahoo.com'
}
]
}
]
}
}
Try string_value .... python uses the field names, not the type name.
I have a dictionary with this structure:
{
"Mark":
{
"surname":"Johnson",
"tags":
[
{
"name":"Salary",
"value":"5"
},
{
"name":"Car manufacturer",
"value":"Volvo"
}
]
},
"John":
{
"surname":"Doe",
"tags":
[
{
"name":"Salary",
"value":"10"
},
{
"name":"Car manufacturer",
"value":"Daewoo"
}
]
}
}
I want to sort that dictionary by value of tag with a name 'Car manufacturer' to get something like this:
{
"Volvo":
{
[
"Mark":{...},...
]
},
"Daewoo":
{
["John":{...}]
}
}
Is there a way to make it as elegant as possible? I can do it by making a couple of nested cycles (example below), but it looks ugly and probably not that efficient.
cars = {}
for person in persons:
for tag in person['tags']:
if tag['name'] == 'Car manufacturer'
cars[tag['value']].append(item)
Honestly, your starting data structure is very poorly designed. It may work on a small scale, but as you progress and your 'dictionary' of items gets larger, well you can already see it gets over whelming quickly. Try instead to make a class, and create different instances of your structure. For example:
class Employees():
def __init__(self):
self.surname = ''
self.salary = 0
self.car_man = [] # if in case you want to add more than one car use a list type or just use string if you plan on keeping this a single value
From here you can create instances, and you would be able to keep track of them much much easier. You can even add these individual instances to a dictionary itself and you can sort them.
EX:
Mark = Employees()
Mark.surname = 'Johnson'
Mark.salary = 5
Mark.car_man = 'Volvo'
John = Employees()
John.surname = "Doe"
John.salary = 10
John.car_man = Daewoo
Do these for as many of them as you want then you could add these instances to a dictionary and be able to sort them much easier.
Adding them to a dictionary is as simple as:
my_dict = {}
my_dict[#key] = # your instance
Dictionary Comprehension - though I tend to shy from it - may make your code more readable if you're that kind of person.
import pprint
pp = pprint.PrettyPrinter(indent=3)
cars = {}
for person in persons:
for tag in persons[person]['tags']:
if tag['name'] == 'Car manufacturer':
if tag['value'] in cars:
cars[tag['value']][person] = persons[person]
else:
cars[tag['value']] = {person:persons[person]}
pp.pprint(cars)
cars = {tag['value']:{person:persons[person]} for person in persons for tag in persons[person]['tags'] if tag['name'] == 'Car manufacturer'}
pp.pprint(cars)
I agree with the others about the structure of your data. Not to mention the code you supplied does not run as provided, so it's hard for us to infer precisely what you want.
I doubt anyone will come up with a much more efficient answer than yours.
Maybe not the most effecient as it needs to generate the dict each time, but your tags list would be better represented as a dict than as a list of dicts with "name" and "value".
sorted(
d.items(),
key=lambda x: dict(
(kv["name"], kv["value"])
for kv in x[1]["tags"]
)["Car manufacturer"]
)
Based on your own answer:
cars = {}
for name in persons:
for tag in persons[name]['tags']:
if tag['name'] == 'Car manufacturer':
cars.setdefault(tag['value'],{})[name] = persons[name]
break
Producing:
{'Daewoo': {'John': {'surname': 'Doe',
'tags': [{'name': 'Salary', 'value': '10'},
{'name': 'Car manufacturer',
'value': 'Daewoo'}]}},
'Volvo': {'Mark': {'surname': 'Johnson',
'tags': [{'name': 'Salary', 'value': '5'},
{'name': 'Car manufacturer', 'value': 'Volvo'}]}}
}
Not very sexy, but probably decently efficient given your datastructure.