Python adding list as a key in dictionary - python

I'm trying to create a dictionary where the key is date ,
In my case each date is a list like this : [2012, 5, 25].
This is the code that I have which reads from a csv file into dictionary.
This code is given I can't change it :
def read_profiles(r_file_name):
"""Reads the file profiles-full.csv into a dictionary where the key is the users id
and the value is a dictionary with users fields "public", "compl_percent", "gender",
"region", "last_login", "age", "body". In addition to this dictionary, the function
returns the list of all users that have 0 completion percentage."""
users = {}
noinfo_users = []
with open(r_file_name, 'rb') as csvfile:
linereader = csv.reader(csvfile)
for line in linereader:
profile = {}
data_fields = ("public", "compl_percent", "gender", "region",
"last_login", "age", "body")
for field, raw_data in zip(data_fields, line[1:]):
if field == "compl_percent" and int(raw_data) == 0:
noinfo_users.append(int(line[0]))
if raw_data == "null":
profile[field] = None
elif field == "body":
profile[field] = raw_data
elif field == "last_login": #<=== reading last_login
profile[field] = map(int, raw_data.split("-"))
elif field == "region":
profile[field] = map(int, raw_data.split(";"))
else:
profile[field] = int(raw_data)
users[int(line[0])] = profile
return users, noinfo_users
And this is the content of the csv file, corresponding to this pattern:
"public", "compl_percent", "gender", "region", "last_login", "age", "body"**
231702, 1, 60, 0, 1;1;21, 2012-05-15, 0, 171 cm;58 kg
This is how an element in profiles dictionary looks like:
1492433: {'body': '160 cm;54 kg', 'compl_percent': 78, 'gender': 0, 'region': [1, 10, 6], 'age': 36, 'last_login': [2012, 5, 25], 'public': 1}
This is my function:
def getStrongConnectedForAttr(user,edges,profiles,attr):
result = dict()
if user in edges:
userFriends = edges.get(user)
for friend in userFriends:
if isBidirectional(edges,user,friend) == 2:
if friend in profiles:
friendAttr = (profiles.get(friend))[str(attr)]
if attr == "last_login":
#friendAttr = '-'.join(map(str, friendAttr))
friendAttr = tuple(friendAttr)
if friendAttr in result: #<===== error
result[friendAttr] = result.get(friendAttr) + 1
else:
result[friendAttr] = 1
return sorted(result.items(), key=operator.itemgetter(1), reverse=True)
else:
return result
It takes profiles as one of the parameters, and builds an empty dictionary.
In the line if friendAttr in result: I get the error:
TypeError: unhashable type: 'list'
I tried searching the web for solution and I found many, especially here on Stack Overflow, and as you can see I tried many solutions, one to convert the list to tuple, or join the list to string.
But none of them worked.

You are only turning the login_attr values to a tuple, but forgetting about the region attribute. It is those values that still throw the exception.
You are only testing for login_attr here:
if attr == "last_login":
friendAttr = tuple(friendAttr)
Rather than turn your values to tuples there, just store tuples when reading the file.
Replace
elif field == "last_login": #<=== reading last_login
profile[field] = map(int, raw_data.split("-"))
elif field == "region":
profile[field] = map(int, raw_data.split(";"))
with
elif field == "last_login":
profile[field] = tuple(map(int, raw_data.split("-")))
elif field == "region":
profile[field] = tuple(map(int, raw_data.split(";")))

Related

how to access an element from a list of dictionaries

I'm trying to build a cart view following a tutorial and I need to print out the quantity of an item. I have two functions in utils.py from where I wanna access the quantity element and print it out in a view, currently getting an error 'dict' object has no attribute 'quantity'
def cookieCart(request):
try:
cart = json.loads(request.COOKIES['cart'])
except:
cart = {}
print('Cart:', cart)
items = []
order = {'get_cart_total': 0, 'get_cart_items': 0, 'shipping': False}
cartItems = order['get_cart_items']
for i in cart:
try:
cartItems += cart[i]["quantity"]
product = Product.objects.get(id=i)
total = (product.final_price * cart[i]["quantity"])
order['get_cart_total'] += total
order['get_cart_items'] += cart[i]["quantity"]
item = {
'product':{
'id':product.id,
'name':product.name,
'final_price':product.final_price,
'image_URL':product.image_URL,
},
**#print the quantity on view**
'quantity':cart[i]["quantity"],
'get_total':total,
}
items.append(item)
except:
pass
return {"items": items, "order": order, "cartItems": cartItems}
def cartData(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
cartItems = order.get_cart_items
else:
cookieData = cookieCart(request)
cartItems = cookieData['cartItems']
order = cookieData['order']
items = cookieData['items']
return {'cartItems':cartItems ,'order':order, 'items':items}
Views
from .utils import cookieCart, cartData
def my_view(request):
data = cartData(request)
items = data['items']
qty = items[0].quantity
print(qty)
Data Structure:
if I print out 'items' instead of 'qty' the data looks like this
[{"product": {"id": 9, "name": "p_one", "final_price": 59, "image_URL": "/images/p_one.jpg"}, "quantity": 2, "get_total": 118}, {"product": {"id": 10, "name": "p_two", "final_price": 32, "image_URL": "/images/p_two.jpg"}, "quantity": 3, "get_total": 96}]
Let's decompose your view :
data = cartData(request)
cartData returns a dict where {"items": list of dicts, ... }
items = data['items']
At this point, items's value is a list of dicts.
To access the first item of a list you use integers indices like
myList[0] # first item in "myList"
myList[1] # second item in "myList"
etc
So here, remember this is a list that contains dicts.
So Items[0] = a dict that is defined in your cookieCart function
item = {
'product':{
'id':product.id,
'name':product.name,
'final_price':product.final_price,
'image_URL':product.image_URL,
},
**#print the quantity on view**
'quantity':cart[i]["quantity"],
'get_total':total,
}
this dict has 3 keys : "product", "quantity" and "get_total".
To access a dict key's value, you use this syntax :
myDict["the key"] # As opposed to lists, you use string keys to match values
So to get the quantity in your case, we could decompose like this :
order = cartData(request) # dict
all_items_in_cart_list = order["items"] # list
first_item_in_cart = all_items_in_cart_list[0] # dict again
quantity_of_first_item = first_item_in_cart["quantity"] # your value !
Not sure how does your data look like, but this is where the problem might be:
def my_view(request):
data = cartData(request)
qty = data['items']['quantity']
# qty = data['items',['quantity']]
print(qty)

An algorithm that turns rows of tabular data into nested objects by ID keys. Can this be implemented better/with a cache?

I wrote code which maps flat, tabular data for related entities (typically stemming from JOIN-like queries) like below:
id,name,artist_id,artist_name,track_id,track_title
4,Let There Be Rock,1,AC/DC,15,Go Down
4,Let There Be Rock,1,AC/DC,16,Dog Eat Dog
Into nested objects like these
[
{
"id": 1,
"name": "Album 1",
"artist": { "id": 1, "name": "Artist 1" },
"tracks": [
{ "id": 1, "name": "Track 1" },
{ "id": 2, "name": "Track 2" }
]
}
]
By using a column-mapping definition object, like:
Definition([
Property("id", "id", is_id=True),
Property("name", "name"),
PropertyObject("artist", [
Property("id", "artist_id", is_id=True),
Property("name", "artist_name"),
]),
PropertyArray("tracks",[
Property("id", "track_id", is_id=True),
Property("name", "track_name"),
])
])
My question is whether it's poorly implemented and if anyone sees a way to implement something like a lookup-cache or other optimizations. I'm not very familiar with algorithms, maybe this is a variant of some standard one?
I've put a runnable example online at repl.it here: https://replit.com/#GavinRay97/WornSeashellDeveloper#main.py
Row = Dict[str, Any]
Result = MutableMapping[str, Any]
def nest(dataset: List[Row], definition: Definition) -> List[Result]:
result = []
properties = definition.properties
primary_id_columns = [p for p in properties if isinstance(p, Property) and p.is_id]
for row in dataset:
mapped_entry = build_entry(primary_id_columns, row, result)
if mapped_entry is None:
continue
for property in properties:
if isinstance(property, Property):
if property.is_id:
continue
extract(property, row, mapped_entry)
elif isinstance(property, PropertyObject):
extract_object(property, row, mapped_entry)
elif isinstance(property, PropertyArray):
extract_array(property, row, mapped_entry)
return result
def extract(property: Property, row: Row, mapped_entry: Result):
mapped_entry[property.name] = row[property.column]
def extract_object(property_object: PropertyObject, row: Row, mapped_entry: Result):
new_entry = {}
for property in property_object.properties:
if isinstance(property, Property):
if property.is_id and row[property.column] is None:
mapped_entry[property_object.name] = None
return
extract(property, row, new_entry)
elif isinstance(property, PropertyObject):
extract_object(property, row, new_entry)
elif isinstance(property, PropertyArray):
extract_array(property, row, new_entry)
mapped_entry[property_object.name] = new_entry
def extract_array(property_array: PropertyArray, row: Row, mapped_entry: Result):
primary_id_columns = [
p for p in property_array.properties if isinstance(p, Property) and p.is_id
]
entry_exists = property_array.name in mapped_entry
list = mapped_entry[property_array.name] if entry_exists else []
mapped = build_entry(primary_id_columns, row, list)
if mapped is None:
return
for property in property_array.properties:
if isinstance(property, Property):
if property.is_id:
continue
extract(property, row, mapped)
elif isinstance(property, PropertyObject):
extract_object(property, row, mapped)
elif isinstance(property, PropertyArray):
extract_array(property, row, mapped)
if not entry_exists:
mapped_entry[property_array.name] = list
def build_entry(primary_id_columns: List[Property], row: Row, result: MutableSequence[Result]) -> Result:
if any(row[p.column] is None for p in primary_id_columns):
return None
existing = next((r for r in result if all(r[p.name] == row[p.column] for p in primary_id_columns) ), None, )
if existing is not None:
return existing
new_entry = {p.name: row[p.column] for p in primary_id_columns}
result.append(new_entry)
return new_entry

Sum all the array that it`s generated from the list

I'm writing a program that gives me how much I spent on the month, I need to sum all the expenses that I had I'm tring to use the sum() function in python but it`s giving me this error :
Traceback (most recent call last):
File "C:/Users/lucas/Desktop/Projeto automacao financeira/pdf.py", line 82, in <module>
a.analyzePdf("Document.pdf")
File "C:/Users/lucas/Desktop/Projeto automacao financeira/pdf.py", line 61, in analyzePdf
print("Sum of elements in given list is :", sum(object))
TypeError: 'float' object is not iterable
What should I do? I already converted from str to float, but I still dont the expected result, heres the code:
class BankAccountReport():
def __init__(self):
self.IV_total_spent = 0.0
self.IV_current_funds = 0.0
self.IV_expenses = {"Day of the month": {}, "Business Expenses": {}, "Transaction ID": {}, "location": "", "cost": 0.0,"personal": ""}
self.IV_deposits = {"Day of the month": {}, "Transaction ID": {}, "location": "", "cost": 0.0}
self.IV_expense_filters = {"Business": {}, "Random": {}, "Search_string": "","Search_type": 0, "Personal": {}}
def analyzePdf(self, pdf_file=None):
call_result = {}
debug_data = []
return_msg = "BankAccountReport:analyzePdf"
date = ""
if type(pdf_file) != str:
return_msg += "input validation failed: pdf_file must be an string that sets where the document is"
return {{'success': RC.input_validation_failed, 'return_msg': return_msg, 'debug_data': debug_data}}
if type(date) != str:
return_msg += "You shouldn`t put "" in the date you are setting to"
return {{'success': RC.input_validation_failed, 'return_msg': return_msg, 'debug_data': debug_data}}
df = wrapper.read_pdf(pdf_file, pages= "all", output_format="csv")
df = df.fillna("0")
df.to_csv("output.csv")
df = pd.read_csv("output.csv", usecols=['Data', "Docto.", "Débito (R$)", "Saldo (R$)"])
df.to_csv("output2.csv")
#print(df)
extract = pd.read_csv('output2.csv')
date = input("what date do you want?")
date_filter = (extract["Data"] == date)
filtered_dates = extract[date_filter]
#print(filtered_dates.head())
data = pd.read_csv("output2.csv", usecols= ["Saldo (R$)"] )
data1 = pd.read_csv("output2.csv", usecols=['Débito (R$)'])
print(data)
names = data.values.tolist()
names1= data1.values.tolist()
print(names1)
print(names)
numbers = df['Saldo (R$)'].str.split().str[1].str.replace(',', '.').apply(float)
numbers1 = df["Débito (R$)"].str.split().str[1].str.replace(",", ".").apply(float)
numbers = numbers.fillna("0")
numbers1 = numbers.fillna("0")
for object in numbers1:
print(object)
print("Sum of elements in given list is :", sum(object))
There is a lot of redundant information, and also a lot of missing information in your question. In particular, we do not know the data types of the columns in numbers1. I guess you want to add all rows, and the items are originally represented as strings. Convert them to floats and sum up:
numbers1.astype(float).sum()
You are probably getting this error because df['Saldo (R$)'].str will not return pandas series.
Probably you need to write your own function such as
def toNumber(str):
return float(str.split().str[1].str.replace(',', '.'))
and in the code you can write
numbers = df['Saldo (R$)'].apply(toNumber)

Django/Python Multiple records

I have a program that compares values from the database and from a CSV file. My program works like this.
Database has values.
User uploads a file (multiple users multiple
files).
The program compares the values from the database and the
CSV files and gives an output.
Which tells me that this particular value was found in this user's file.
But I want the program to show me that if the value was found in the other user's file or not.
Here is a working example.
DB Values = [1,23,33,445,6656,88]
Example values of the CSV files:
File 1 values = [1,23,445,77,66,556,54]
File 2 values = [1,23,45,77,366]
File 3 values = [1,23,5,77,5356,524]
Output needed:
{'1':[(user1, some value),(user2, some value)...]}
Here my code:
def LCR(request):
template = "LCR\LCRGen.html"
dest = Destination.objects.values_list('dest_num', flat=True)
ratelist = { }
csv_file = { }
data_set = { }
io_string = { }
vendor = RateFile.objects.values_list()
v_count = vendor.count()
for v_id, v_name, v_file in vendor:
vendor_name = str(v_name)
vendornames = str(v_name)
vendornames = { }
for desNum in dest:
desNum = str(desNum)
for countvar in range(v_count):
csv_file[vendor_name] = RateFile.objects.get(id=v_id).ven_file
data_set[vendor_name] = csv_file[vendor_name].read().decode("UTF-8")
io_string[vendor_name] = io.StringIO(data_set[vendor_name])
next(io_string[vendor_name])
for column in csv.reader(io_string[vendor_name], delimiter=str(u",")):
vendornames[column[0]] = column[1]
for venNum, venValue in vendornames.items():
venlen = len(venNum)
deslen = len(desNum)
if venlen >= deslen or venlen <= deslen:
if desNum[:-1] == venNum[:-1] and desNum[:-2] == venNum[:-2] and desNum[:-3] == venNum[:-3]:
ratelist[desNum] = [(vendor_name, venValue),]
if (vendor_name, venValue) in ratelist[desNum]:
ratelist[desNum] = [
(vendor_name, venValue),]
elif desNum[:-1] == venNum[:-2] and desNum[:-2] == venNum[:-3] and desNum[:-3] == venNum[:-4]:
ratelist[desNum] = [(vendor_name, venValue),]
if (vendor_name, venValue) in ratelist[desNum]:
ratelist[desNum] = [
(vendor_name, venValue),]
elif desNum[:-1] == desNum[:-3] and desNum[:-2] == venNum[:-4] and desNum[:-3] == venNum[:-5]:
ratelist[desNum] = [(vendor_name, venValue),]
elif desNum[:-1] == venNum[:-5] and desNum[:-2] == venNum[:-6]:
ratelist[desNum] = [(vendor_name, venValue),]
if (vendor_name, venValue) in ratelist[desNum]:
ratelist[desNum] = [
(vendor_name, venValue),]
else:
pass
print ( ratelist )
return render ( request, template, { "ratelist" : ratelist } )
Output
Zong, Tata are usernames and the float values is their respective value for the key value of the dictionary.
{'12': [('Zong', ' 0.026')], '213': [('Tata', ' 4.150')], '49': [('Tata', ' 0.531')], '30': [('Zong', ' 0.87')], '454': [('Tata', ' 0.531')], '374': [('Zong', ' 0.87')],
This is what you asked for:
### your data example
db = [1,23,33,445,66,556,88]
us1 = [1,23,445,77,66,556,54]
us2 = [1,23,45,77,366]
### create a list of usernames (to use the string name in dictionary)
userlist = [ "us1", "us2" ]
### intialize the dict for results
values_dict = {}
### open the loop on DB values
for value in db :
# open loop on userlist
for user in userlist :
# if value is found in user list of values
if value in eval(user) :
# if values still NOT a key of results dictionary create the key with the tuple list as values
if value not in values_dict :
values_dict.update({ value : [ ( user, value ) ] })
# else just append the tuple (username, value) to the results dictionary for the DB value corresponding key
else :
values_dict[value].append([ ( user, value ) ])
values_dict
### OUTPUT:
{1: [('us1', 1), [('us2', 1)]], 23: [('us1', 23), [('us2', 23)]], 445: [('us1', 445)], 66: [('us1', 66)], 556: [('us1', 556)]}
but it makes no sense cause it simply check if a value is in the user list of values and add a tuple just to confirm it, it doesn't require all this code, could be simplified a lot. But I'm thinking that I misunderstood your question (please review the english), probably you need to use the DB value as the key to retrieve another value from the user...please review and update

Split dictionary key and list of values from dict

I want to split keys and values and display the dictionary result below mentioned format. I'm reading a file and splitting the data into list and later moving to dictionary.
Please help me to get the result.
INPUT FILE - commands.txt
login url=http://demo.url.net username=test#url.net password=mytester
create-folder foldername=demo
select-folder foldername=test123
logout
Expected result format
print result_dict
"0": {
"login": [
{
"url": "http://demo.url.net",
"username": "test#url.net",
"password": "mytester"
}
]
},
"1": {
"create-folder": {
"foldername": "demo"
}
},
"2": {
"select-folder": {
"foldername": "test-folder"
}
},
"3": {
"logout": {}
}
CODE
file=os.path.abspath('catalog/commands.txt')
list_output=[f.rstrip().split() for f in open(file).readlines()]
print list_output
counter=0
for data in list_output:
csvdata[counter]=data[0:]
counter=counter+1
print csvdata
for key,val in csvdata.iteritems():
for item in val:
if '=' in item:
key,value=item.split("=")
result[key]=value
print result
As a function:
from collections import defaultdict
from itertools import count
def read_file(file_path):
result = defaultdict(dict)
item = count()
with open(file_path) as f:
for line in f:
if not line:
continue
parts = line.split()
result[next(item)][parts[0]] = dict(p.split('=') for p in parts[1:])
return dict(result)
Better example and explanation:
s = """
login url=http://demo.url.net username=test#url.net password=mytester
create-folder foldername=demo
select-folder foldername=test123
logout
"""
from collections import defaultdict
from itertools import count
result_dict = defaultdict(dict)
item = count()
# pretend you opened the file and are reading it line by line
for line in s.splitlines():
if not line:
continue # skip empty lines
parts = line.split()
result_dict[next(item)][parts[0]] = dict(p.split('=') for p in parts[1:])
With pretty print:
>>> pprint(dict(result_dict))
{0: {'login': {'password': 'mytester',
'url': 'http://demo.url.net',
'username': 'test#url.net'}},
1: {'create-folder': {'foldername': 'demo'}},
2: {'select-folder': {'foldername': 'test123'}},
3: {'logout': {}}}
lines = ["login url=http://demo.url.net username=test#url.net password=mytester",
"create-folder foldername=demo",
"select-folder foldername=test123",
"logout"]
result = {}
for no, line in enumerate(lines):
values = line.split()
pairs = [v.split('=') for v in values[1:]]
result[str(no)] = {values[0]: [dict(pairs)] if len(pairs) > 1 else dict(pairs)}
import pprint
pprint.pprint(result)
Output:
{'0': {'login': [{'password': 'mytester',
'url': 'http://demo.url.net',
'username': 'test#url.net'}]},
'1': {'create-folder': {'foldername': 'demo'}},
'2': {'select-folder': {'foldername': 'test123'}},
'3': {'logout': {}}}
But are you sure you need the extra list inside the login value? If not, just change [dict(pairs)] if len(pairs) > 1 else dict(pairs) to dict(pairs).
r = dict()
f = open('commands.txt')
for i, line in enumerate(f.readlines()):
r[str(i)] = dict()
actions = line.split()
list_actions = {}
for action in actions[1:]:
if "=" in action:
k, v = action.split('=')
list_actions[k] = v
if len(actions[1:]) > 1:
r[str(i)][actions[0]] = [list_actions]
else:
r[str(i)][actions[0]] = list_actions
print r
Should be work

Categories