How To Append String To Dictionary in Python within Forloop - python

i need to append a value of string to a specific key in dictionary in python within forloop, and if the data in forloop is empty then give the value of empty string which i'm not able to get it right, here is some of the code,
top100 = {}
for product in product_list:
title = product.xpath('a[#class="someClass"]/text()') # LIST of 100
price = product.xpath('div[#class="someClass"]/text()') # LIST of 100
# the value in the title is list of 100 title
# more like ['title1', 'title2', ...] and so the price [100, 230, ...]
# how to append each pairs of title and price so i have list of dictionary
top100['title'].append(title)
top100['price'].append(price)
print( top100)
output:
KeyError: 'title'
but i need something more like:
top100 = [{'title': 'title1', 'price': 'price1'},
{'title': 'title2', 'price': 'price2'}
]

The top 100 variable should be a list, then append a dictionary
top100 = []
for product in product_list:
title = product.xpath('a[#class="someClass"]/text()') # LIST of 100
price = product.xpath('div[#class="someClass"]/text()') # LIST of 100
top100.append({'title':title,'price':price})
print( top100)

You need to make top100 a list with many nested dictionaries, with the following code:
top100 = []
for product in product_list:
title = product.xpath('a[#class="someClass"]/text()') # LIST of 100
price = product.xpath('div[#class="someClass"]/text()') # LIST of 100
top100.append({'title':title,'price':price})

Here for the another version of result
top100 = {'title':[],'price':[]}
for product in product_list:
title = product.xpath('a[#class="someClass"]/text()') # LIST of 100
price = product.xpath('div[#class="someClass"]/text()') # LIST of 100
top100['title'].append(title)
top100['price'].append(price)
print( top100)
This should output
{'title':[..., ..., ... ],'price':[..., ..., ...]}

thanks for the answer i was able to find my own solution,
top100 = []
for product in product_list:
titles = product.xpath('a[#class="someLink"]/text()')
prices = product.xpath('div[#class="somePrice"]/text()')
for title, price, in zip(titles, prices):
top100.append({'title':title, 'price':price})
output:
top100 = [{'title': 'title1', 'price': '100'},
{'title': 'title2', 'price': '200'}]

Related

How to create a nested dictionary from multiple list?

How do I combine three separate list into one single dictionary?
Currently I have three operator inputs, where each input is split into a list.
item_input = input("Enter products seperated by space")
price_input = input("Enter price seperated by space")
stock_input = input("Enter stock seperated by space")
items = item_input.split()
price = price_input.split()
stock = stock_input.split()
I assume my first step would be to combine the price_input and stock_input into one dictionary first, and then nest them into the products_input.
I've tried using the fromkey method to make the price_input in its own dictionary to start with but the keys and values are in the opposite positions that I want
Example code:
price = [1,2,3]
price_dict = dict.fromkeys (price, "price")
#Output = {1: 'price', 2: 'price', 3: 'price'}
#Inteded output = {"price": 1, "price": 2, "price": 3}
This is the intended final output that I need.
products = {
"apple": {"price": 3.5, "stock": 134},
"banana": {"price": 6.82, "stock": 52},
"cake": {"price": 23, "stock": 5}
}
You could do this with a dictionary comprehension:
answer={x[0]: {"price": x[1], "stock" : x[2]} for x in zip(items, price, stock)}
This is similar to a list comprehension but returns a dictionary.
zip(items, price, stock) turns the three lists into a single list of tuples. Actually it is probably an generator - but here the effect here is the same.
Then it just iterate over this joined List/generator and construct each entry of the final dictionary.
You can zip item, price and stock together and then just use a dictionary comprehension:
items = input("Items: ").split()
prices = map(float, input("Prices: ").split())
stocks = map(int, input("Stocks: ").split())
products = {
item: {"price": price, "stock": stock}
for item, price, stock in zip(items, prices, stocks)
}
However, it might be better if the user could enter items one by one instead of having to add all at once so you could use a loop for that, the user inputs values separated by comma and to exit just doesn't type anything, simply pressers enter key.
products = {}
new_product = input("Item, price, stock: ")
while new_product:
item, price, stock = new_product.split(",")
products[item.strip()] = {"price": float(price), "stock": int(stock)}
new_product = input("Item, price, stock: ")

How to add keys and values to a dict in a loop?

Trying to create a dict that holds name,position and number for each player for each team. But when trying to create the final dictionary players[team_name] =dict(zip(number,name,position)) it throws an error (see below). I can't seem to get it right, any thoughts on what I'm doing wrong here would be highly appreciated. Many thanks,
from bs4 import BeautifulSoup as soup
import requests
from lxml import html
clubs_url = 'https://www.premierleague.com/clubs'
parent_url = clubs_url.rsplit('/', 1)[0]
data = requests.get(clubs_url).text
html = soup(data, 'html.parser')
team_name = []
team_link = []
for ul in html.find_all('ul', {'class': 'block-list-5 block-list-3-m block-list-1-s block-list-1-xs block-list-padding dataContainer'}):
for a in ul.find_all('a'):
team_name.append(str(a.h4).split('>', 1)[1].split('<')[0])
team_link.append(parent_url+a['href'])
team_link = [item.replace('overview', 'squad') for item in team_link]
team = dict(zip(team_name, team_link))
data = {}
players = {}
for team_name, team_link in team.items():
player_page = requests.get(team_link)
cont = soup(player_page.content, 'lxml')
clud_ele = cont.find_all('span', attrs={'class' : 'playerCardInfo'})
for i in clud_ele:
v_number = [100 if v == "-" else v.get_text(strip=True) for v in i.select('span.number')]
v_name = [v.get_text(strip=True) for v in i.select('h4.name')]
v_position = [v.get_text(strip=True) for v in i.select('span.position')]
key_number = [key for element in i.select('span.number') for key in element['class']]
key_name = [key for element in i.select('h4.name') for key in element['class']]
key_position = [key for element in i.select('span.position') for key in element['class']]
number = dict(zip(key_number,v_number))
name = dict(zip(key_name,v_name))
position = dict(zip(key_position,v_name))
players[team_name] = dict(zip(number,name,position))
---> 21 players[team_name] = dict(zip(number,name,position))
22
23
ValueError: dictionary update sequence element #0 has length 3; 2 is required
There are many problems in your code. The one causing the error is that you are trying to instantiate a dictionary with a 3-items tuple in list which is not possible. See the dict doc for details.
That said, I would suggest to rework the whole nested loop.
First, you have in clud_ele a list of player info, each player info concerns only one player and provides only one position, only one name and only one number. So there is no need to store those informations in lists, you could use simple variables:
for player_info in clud_ele:
number = player_info.select('span.number')[0].get_text(strip=True)
if number == '-':
number = 100
name = player_info.select('h4.name')[0].get_text(strip=True)
position = player_info.select('span.position')[0].get_text(strip=True)
Here, usage of select method returns a list but since you know that the list contains only one item, it's ok to get this item to call get_text on. But you could check that the player_info.select('span.number') length is actually 1 before continuing to work if you want to be sure...
This way, you get scalar data type which will be much easier to manipulate.
Also note that I renamed the i to player_info which is much more explicit.
Then you can easily add your player data to your players dict:
players[team_name].append({'name': name,
'position': position
'number': number})
This assume that you create the players[team_name] before the nested loop with players[team_name] = [].
Edit: as stated in the #kederrac's answer, usage of a defaultdict is a smart and convenient way to avoid the manual creation of each players[team_name] list
Finally, this will give you:
a dictionary containing values for name, position and number keys for each player
a team list containg player dictionaries for each team
a players dictionary associating a team list for each team_name
It is the data structure you seems to want, but other structures are possible. Remember to think about your data structure to make it logical AND easily manipulable.
you can't instantiate a dict with 3 arguments, the problem is the fact that you have 3 variables in the zip: zip(number, name, position) with which you want to instantiate a dict, you should give only 2 arguments at a time, the key and the value
I've rewritten your las part of the code:
from collections import defaultdict
data = {}
players = defaultdict(list)
for team_name, team_link in team.items():
player_page = requests.get(team_link)
cont = soup(player_page.text, 'lxml')
clud_ele = cont.find_all('span', attrs={'class' : 'playerCardInfo'})
for i in clud_ele:
num = i.select('span.number')[0].get_text(strip=True)
number = 100 if num == '-' else num
name = i.select('h4.name')[0].get_text(strip=True)
position = i.select('span.position')[0].get_text(strip=True)
players[team_name].append({'number': number, 'position': position, 'name': name})
output:
defaultdict(list,
{'Arsenal': [{'number': '1',
'position': 'Goalkeeper',
'name': 'Bernd Leno'},
{'number': '26',
'position': 'Goalkeeper',
'name': 'Emiliano Martínez'},
{'number': '33', 'position': 'Goalkeeper', 'name': 'Matt Macey'},
{'number': '2',
'position': 'Defender',
'name': 'Héctor Bellerín'},
.......................

Getting associated values from Python dictionary that is using lists

Ok, so I am working on an application that can go through a number of different database objects, compare the string and return the associated id, first name and last name. I currently have it to where I am building a list of tuples and then populating a dictionary with the key and values(using a list). What I want to do next is find the Max percentage and then return the associated fist and last name from the dictionary. I know the description is a little confusing so please look at the below examples and code:
# My Dictionary:
{'percent': [51.9, 52.3, 81.8, 21.0], 'first_name': ['Bob', 'Bill', 'Matt', 'John'], 'last_name': ['Smith', 'Allen', 'Naran', 'Jacobs']}
# I would want this to be returned:
percent = 81.8 (Max percentage match)
first_name = 'Matt' (First name associated with the max percentage match)
last_name = 'Naran' (Last name associated with the max percentage match)
# Code so Far:
compare_list = []
compare_dict = {}
# Builds my list of Tuples
compare_list.append(tuple(("percent", percentage)))
compare_list.append(tuple(("first_name", first_name)))
compare_list.append(tuple(("last_name", last_name)))
# Builds my Dictionary
for x, y in compare_list:
compare_dict.setdefault(x, []).append(y)
Not sure where to go to return the first and last name associated with the Max percentage.
I really appreciate any and all help that you provide!
I hope this will help you:
data = {'percent': [51.9, 52.3, 81.8, 21.0], 'first_name': ['Bob', 'Bill', 'Matt', 'John'], 'last_name': ['Smith', 'Allen', 'Naran', 'Jacobs']}
percentage_list = data['percent']
percentage = max(percentage_list)
max_index = percentage_list.index(percentage)
first_name = data['first_name'][max_index]
last_name = data['last_name'][max_index]
# Code so Far:
compare_list = []
compare_dict = {}
# Builds my list of Tuples
compare_list.append(tuple(("percent", percentage)))
compare_list.append(tuple(("first_name", first_name)))
compare_list.append(tuple(("last_name", last_name)))
# Builds my Dictionary
for x, y in compare_list:
compare_dict.setdefault(x, []).append(y)
print compare_dict

python dictionary - list of lists to dict

I'm trying to take list of lists and convert in to dictionary. See code below
yearend = [['empl','rating1','rating2','rating3'],['mike','4','4','5'],
['sam','3','2','5'],['doug','5','5','5']]
extract the employee names
employee = [item[0] for item in yearend] #select 1st item from each list
employee.pop(0) # pop out the empl
print(employee)
### output##################################################
##['mike', 'sam', 'doug']###################################
###Output###################################################
###extract the various rating types
yearend1 = yearend [:] # make a copy
rating = yearend1.pop(0) # Pop out the 1st list
rating.pop(0)
print(rating)
### output##################################################
##['rating1', 'rating2', 'rating3']#########################
###Output###################################################
# pick employee and rating and convert rating to numeric
empl_rating = {t[0]:t[1:] for t in yearend1}
for key,value in empl_rating.items():
value = list(map(int, value))
empl_rating[key] = value
print(empl_rating)
### output##################################################
##{'mike': [4, 4, 5], 'sam': [3, 2, 5], 'doug': [5, 5, 5]}##
###Output###################################################
I extracted the data like above and now Iam trying to put together in to dict (New_dicts) so that when
New_dicts['sam']['rating1']
I get 3 or
New_dicts['doug']['rating3']
I get 5. What I'm struggling is how to put this data together?
def todict(ratings) :
a ={}
a["rating1"] = ratings [0]
a["rating2"] = ratings [1]
a["rating3"] = ratings [2]
return a
One way to solve your problem is to get rid of the first row with the headings then just do:
{item[0] : todict(item[1:])
for item in your_list}
BTW this sol is based of off how you wanted to index it. I'm sure there is a more generic sol out there.
Because what you want is essentially just a nested dict
You can use a dict comprehension:
New_dicts = {line[0]: {yearend[0][i + 1]: int(rating) for i, rating in enumerate(line[1:])} for line in yearend[1:]}

Python Dictionary - find average of value from other values

I have the following list
count = 3.5, price = 2500
count = 3, price = 400
count = 2, price = 3000
count = 3.5, price = 750
count = 2, price = 500
I want to find the average price for all where the count is the same. For example:
count = 2, price = 3000
count = 2, price = 500
3000 + 500 = 3500
3500/2 = 1750
Avg for 'count 2' is 1750
Here's my code so far
avg_list = [value["average"] for value in dictionary_database_list]
counter_obj = collections.Counter(count_list)
print ("AVG:")
for i in counter_obj:
print (i, counter_obj[i])
I'll admit I'm not 100% clear on what you're looking for here, but I'll give it a shot:
A good strategy when you want to iterate over a list of "things" and accumulate some kind of information about "the same kind of thing" is to use a hash table. In Python, we usually use a dict for algorithms that require a hash table.
To collect enough information to get the average price for each item in your list, we need:
a) the total number of items with a specific "count"
b) the total price of items with a specific "count"
So let's build a data structure that maps a "count" to a dict containing "total items" and "total price" for the item with that "count".
Let's take our input in the format:
item_list = [
{'count': 3.5, 'price': 2500},
{'count': 3, 'price': 400},
{'count': 2, 'price': 3000},
{'count': 3.5, 'price': 750},
{'count': 2, 'price': 500},
]
Now let's map the info about "total items" and "total price" in a dict called items_by_count:
for item in item_list:
count, price = item['count'], item['price']
items_by_count[count]['total_items'] += 1
items_by_count[count]['total_price'] += price
But wait! items_by_count[count] will throw a KeyError if count isn't already in the dict. This is a good use case for defaultdict. Let's define the default value of a count we've never seen before as 0 total price, and 0 total items:
from collections import defaultdict
items_by_count = defaultdict(lambda: {
'total_items': 0,
'total_price': 0
})
Now our code won't throw an exception every time we see a new value for count.
Finally, we need to actually take the average. Let's get the information we need in another dict, mapping count to average price. This is a good use case for a dict comprehension:
{count: item['total_price'] / item['total_items']
for count, item in items_by_count.iteritems()}
This iterates over the items_by_count dict and creates the new dict that we want.
Putting it all together:
from collections import defaultdict
def get_average_price(item_list):
items_by_count = defaultdict(lambda: {
'total_items': 0,
'total_price': 0
})
for item in item_list:
count, price = item['count'], item['price']
items_by_count[count]['total_items'] += 1
items_by_count[count]['total_price'] += price
return {count: item['total_price'] / item['total_items']
for count, item in items_by_count.iteritems()}
If we pass in our example input dict, this function returns:
{3.5: 1625, 2: 1750, 3: 400}
Which is hopefully the output you want! Be cautious of gotchas like float division in your particular Python version.
You need to iterate over your items
See documentation
avg(dictionary.values()) is probably what you want

Categories