bank = {'id':{'moneys':{}}}
with open(bankID.txt, 'r') as a:
for key in a.readlines():
bank['id']=[str(key)[0:3]]
with open(banknumbers.txt) as b:
for value in b.readlines():
bankID = value[0:3]
bankMoney = int(value[4:9])
if bank['id'] == bankID:
bank['id]['money']= bankMoney
#bank[bankID] = bankMoney <--this one kinda works but it isnt right.
#an example of the 2nd txt file would look like
#234 8763 so id number and money respectively
How come my first forloop does not assign all my id with a key. when I print (bank['id']) the only value that comes out is the first key read.
In my first txt file it only has the bank id and the second txt file has the bank id and the amount of money after it. I cant seem to figure out how to compare the bank id of my dictionary and the bank id of the 2nd txt file and assign the value for money.
So I want the output to look like {'875': 234,'576': 345, '676': 8837}
How come my first forloop does not assign all my id with a key.
Because you're telling it to assign the key "id" the value [str(key)[0:3]]
So you wind up with exactly one key, the string literal "id" and whatever the last value of [str(key)[0:3]] was.
You don't actually need a dictionary within a dictionary unless you have 3 values to keep track of, like a bankId, transactionId and amount.
Suppose banknumbers.txt looked like this instead:
# 234 8763 44.55 -- so a bank number, a transaction number and some money.
This would give you a dictionary within a dictionary for that:
bank = {}
with open(bankID.txt, 'r') as a:
for key in a.readlines():
bank[str(key)[0:3]] = {}
with open(banknumbers.txt) as b:
for value in b.readlines():
bankID = value[0:3]
transactionId = int(value[4:9])
money = float(value(9:19))
bank[bankID][transactionId] = money
You should probably go read the relevant section of the python tutorial: https://docs.python.org/2/tutorial/datastructures.html#dictionaries
I think you're misunderstanding dictionaries. You're overwriting bank['id'] every iteration in the for loop. I'm not exactly sure what you want, but you may want to have a list of banks. The code would be:
bank = []
with open(bankID.txt, 'r') as a:
for key in a.readlines():
bank.append({'id':[str(key)[0:3]], 'moneys': 0})
with open(banknumbers.txt) as b:
for value in b.readlines():
bankID = value[0:3]
bankMoney = int(value[4:9])
for bnk in bank:
if bnk['id'] == bankID:
bnk['money'] = bankMoney
Related
I am trying to read values that were stored in mydict. I keep getting invalid response when running the program. The Excel sheet is formatted by year, location, id, power, and isload. My goal is to print the information associated all the information based off the year and location number.
data = list(csv.reader(open(LOAD_GEN_DATAFILE)))
# read the entire CSV into Python.
# assume CSV has columns as described in the doc string
keyinput=input("Select Year of Study: ")
year=keyinput
mydict={"locA":1,"locb":2}
keyinput2=input(" Select the number associated to the TLA Pocket Location:")
if keyinput2 in mydict:
location=keyinput2
else:
print("Invalid Number")
for year,location,bus,change,isload in data:
# convert the types from string to Python numbers
change= float(change)
bus = int(bus)
if isload.isdigit() and int(isload):
print()
else:
exit
I suspect that you are putting in a number (example 2) and expecting the dictionary to tell you if that value is in the dict or not. However the dictionaries "in" operator works on keys, not values.
Consider this:
mydict = {"a" : 1, "b": 2}
print("Is 1 in mydict? ", 1 in mydict)
print("Is a in mydict? ", "a" in mydict)
print("Is 1 in mydicts values? ", 1 in mydict.values())
Output:
Is 1 in mydict? False
Is a in mydict? True
Is 1 in mydicts values? True
Keep in mind that asking whether a value is in a dict or not is a O(n) operation, the program may have to look at every value in order to determine if that value is in the dictionary or not. However asking if a key is in a dictionary is O(1) (very fast).
If you are always looking up the location based on the number, consider switching the keys/values of your dict around like this:
mydict={1:"locA",2:"locb"}
I don't know much about reading from an excel document or about the nature of the data you have, but assuming your for loop works, here is how you might load the values into the dict:
data = list(csv.reader(open(LOAD_GEN_DATAFILE)))
mydict = {}
for row in data:
year,location,bus,change,isload = row[0:5]
# convert the types from string to Python numbers
change= float(change)
bus = int(bus)
# If this is a year not seen before, add it to the dictionary
if year not in mydict:
mydict[year] = {}
busses_in_year = mydict[year]
if location not in busses_in_year:
busses_in_year[location] = []
# Add the bus to the list of busses that stop at this location
busses_in_year[location].append((bus, change, isload))
# assume CSV has columns as described in the doc string
year = input("Select Year of Study: ")
location = input(" Select the number associated to the TLA Pocket Location:")
if year in mydict and location in mydict[year]:
busses_in_year = mydict[year]
print("Here are all the busses at that location for that year: ")
for bus in busses_in_year[location]:
print(bus)
else:
print("Invalid Year or Location")
Since you are using two keys to group/access the data, you can use nested dictionaries to solve this. Note the syntax to put things into and access things from a dictionary is dict_name[key] = value and value = dict_name[key] respectively.
I wrote a code that takes in some data, and I end up with a csv file that looks like the following:
1,Steak,Martins
2,Fish,Martins
2,Steak,Johnsons
4,Veggie,Smiths
3,Chicken,Johnsons
1,Veggie,Johnsons
where the first column is a quantity, the second column is the type of item (in this case the meal), and the third column is an identifier (in this case it is family name). I need to print this information to a text file in a specific way:
Martins
1 Steak
2 Fish
Johnsons
2 Steak
3 Chicken
1 Veggie
Smiths
4 Veggie
So What I want is the family name followed by what that family ordered. I wrote the following code to accomplish this, but it doesn't seem to be quite there.
import csv
orders = "orders.txt"
messy_orders = "needs_sorting.csv"
with open(messy_orders, 'rb') as orders_for_sorting, open(orders, 'a') as final_orders_file:
comp = []
reader_sorting = csv.reader(orders_for_sorting)
for row in reader_sorting:
test_bit = [row[2]]
if test_bit not in comp:
comp.append(test_bit)
final_orders_file.write(row[2])
for row in reader_sorting:
if [row[2]] == test_bit:
final_orders_file.write(row[0], row[1])
else:
print "already here"
continue
What I end up with is the following
Martins
2 Fish
Additionally, I never see it print "already here" though I think I should if it were working properly. What I suspect is happening is that the program goes through the second for loop, then exits the program without continuing the first loop. Unfortunately I'm not sure how to make it go back to the original loop once it has identified and printed all instances of a given family name in a file. I thought The reason I have it set up this way, is so that I can get the family name written as a header. Otherwise I would just sort the file by family name. Please note that after running the orders through my first program, I did manage to sort everything such that each row represents the complete quantity of that type of food for that family (there are no recurring instances of a row containing both Steak and Martins).
This is a problem that you solve with a dictionary; which will accumulate your items by the last name (family name) of your file.
The second thing you have to do is accumulate a total of each type of meal - keeping in mind that the data you are reading is a string, and not an integer that you can add, so you'll have to do some conversion.
To put all that together, try this snippet:
import csv
d = dict()
with open(r'd:/file.csv') as f:
reader = csv.reader(f)
for row in reader:
# if the family name doesn't
# exist in our dictionary,
# set it with a default value of a blank dictionary
if row[2] not in d:
d[row[2]] = dict()
# If the meal type doesn't exist for this
# family, set it up as a key in their dictionary
# and set the value to int value of the count
if row[1] not in d[row[2]]:
d[row[2]][row[1]] = int(row[0])
else:
# Both the family and the meal already
# exist in the dictionary, so just add the
# count to the total
d[row[2]][row[1]] += int(row[0])
Once you run through that loop, d looks like this:
{'Johnsons': {'Chicken': 3, 'Steak': 2, 'Veggie': 1},
'Martins': {'Fish': 2, 'Steak': 1},
'Smiths': {'Veggie': 4}}
Now its just a matter of printing it out:
for family,data in d.iteritems():
print('{}'.format(family))
for meal, total in data.iteritems():
print('{} {}'.format(total, meal))
At the end of the loop, you'll have:
Johnsons
3 Chicken
2 Steak
1 Veggie
Smiths
4 Veggie
Martins
2 Fish
1 Steak
You can later improve this snippet by using defaultdict
First time replier so here's a go. Have you considered keeping track of the orders and then writing to a file? I tried something using a dict based approach and it seems to work fine. The idea was to index by the family name and store a list of pairs containing the order quantities and types.
You may also want to consider the readability of your code - it's hard to follow and debug. However, what I think is happening is the line
for line in reader_sorting:
Iterates through reader_sorting. You read the 1st name, extract the family name, and later proceed to iterate again in reader_sorting. This time you start at the 2nd line, which family name matches, and you print it successfully. The rest of the line don't match, but you still iterate through them all. Now you've finished iterating through reader_sorting, and the loop finishes, even though in the outer loop you've read only one line.
One solution may be to create another iterator in the outer for loop and not expend the iterator that loop goes through. However, then you still need to deal with the possibility of double counting, or keeping track of indices. Another way may be to keep of the orders by family as you iterate.
import csv
orders = {}
with open('needs_sorting.csv') as file:
needs_sorting = csv.reader(file)
for amount, meal, family in needs_sorting:
if family not in orders:
orders[family] = []
orders[family].append((amount, meal))
with open('orders.txt', 'a') as file:
for family in orders:
file.write('%s\n' % family)
for amount, meal in orders[family]:
file.write('%s %s\n' % (amount, meal))
Update: Apparently, I noticed that in my main code, when I extract the values from the list of dictionaries that I get from readExpenses.py, I store it as a set, not as a list of dictionaries.
Now, I know that I store each dictionary in the 'exp' list with these lines of code:
for e in expenses:
exp.append(e)
However, I only want the Keys Amount, and Type from those dictionaries, and not the other entries.
For reference, here is the list of keys in an expense dictionary:
"Date","Description","Type","Check Number","Amount","Balance"
As mentioned before, I only need Type and Amount.
I am trying to make a budget program, So I have this list of dictionaries:
[{'Bills': 30.0}, {'Bills': 101.53}, {'Bills': 60.0}, {'Bills': 52.45}, {'Gas': 51.17}, {500.0: 'Mortgage'}, {'Food': 5.1}]
And I'm trying to compare it to this list of dictionaries:
[{400.0: 'Bills'}, {'Gas': 100.0}, {500.0: 'Mortgage'}, {'Food': 45.0}]
The first list is how much money I spent on different services in a given month, and what category it was in, and the second dictionary is the max amount that the budget allows me to spend on said category.
The goal is, in the first dictionary, to combine all the values of the same key into one key:value pair, then compare it to the second dictionary.
So I should get this list of dictionaries out of the first one:
[{'Bills': 295.15), {'Gas': 51.17}, {500.0: 'Mortgage'}, {'Food': 5.1}]
I tried looking at this example and this one, but they are just about merging the dictionaries lists together, and not summing the values of the same key. I did try the code in the latter, but it only joined the dictionaries together. I noticed that sum only seems to work with "raw" dictionaries, and not with lists of dictionaries.
I did try this as a thought experiment:
print(sum(item['amount'] for item in exp))
I know that would sum up all the numbers under amount, rather than return a number for each category, but I wanted to try out it for the heck of it, to see if it would lead to a solution, but I got this error in return:
TypeError: 'set' object is not subscriptable
The Counter function seemed to show promise as a solution as well when I was messing around, however, it seems to only work with dictionaries that are on their own, and not with list of dictionaries.
#where exp is the first dictionary that I mentioned
a = Counter(exp)
b = Counter(exp)
c = a + b #I'm aware the math would have be faulty on this, but this was a test run
print (c)
This attempt returned this error:
TypeError: unhashable type: 'set'
Also, is there a way to do it without importing the collections module and using what comes with python as well?
My code:
from readExpense import *
from budget import *
from collections import *
#Returns the expenses by expenses type
def expensesByType(expenses, budget):
exp = []
expByType = []
bud = []
for e in expenses:
entry = {e['exptype'], e['amount']}
exp.append(entry)
for b in budget:
entry = {b['exptype'], b['maxamnt']}
bud.append(entry)
return expByType;
def Main():
budget = readBudget("budget.txt")
#printBudget(budget)
expenses = readExpenses("expenses.txt")
#printExpenses(expenses)
expByType = expensesByType(expenses, budget)
if __name__ == '__main__':
Main()
And for reference, the code from budget and readexpense respectively.
budget.py
def readBudget(budgetFile):
# Read the file into list lines
f = open(budgetFile)
lines = f.readlines()
f.close()
budget = []
# Parse the lines
for i in range(len(lines)):
list = lines[i].split(",")
exptype = list[0].strip('" \n')
if exptype == "Type":
continue
maxamount = list[1].strip('$" \n\r')
entry = {'exptype':exptype, 'maxamnt':float(maxamount)}
budget.append(entry)
return budget
def printBudget(budget):
print()
print("================= BUDGET ==================")
print("Type".ljust(12), "Max Amount".ljust(12))
total = 0
for b in budget:
print(b['exptype'].ljust(12), str("$%0.2f" %b['maxamnt']).ljust(50))
total = total + b['maxamnt']
print("Total: ", "$%0.2f" % total)
def Main():
budget = readBudget("budget.txt")
printBudget(budget)
if __name__ == '__main__':
Main()
readExpense.py
def readExpenses(file):
#read file into list of lines
#split lines into fields
# for each list create a dictionary
# add dictionary to expense list
#return expenses in a list of dictionary with fields
# date desc, exptype checknm, amnt
f = open(file)
lines=f.readlines()
f.close()
expenses = []
for i in range(len(lines)):
list = lines[i].split(",")
date = list[0].strip('" \n')
if date == "Date":
continue
description = list[1].strip('" \n\r')
exptype= list[2].strip('" \n\r')
checkNum = list[3].strip('" \n\r')
amount = list[4].strip('($)" \n\r')
balance = list[5].strip('" \n\r')
entry ={'date':date, 'description': description, 'exptype':exptype, 'checkNum':checkNum, 'amount':float(amount), 'balance': balance}
expenses.append(entry)
return expenses
def printExpenses(expenses):
#print expenses
print()
print("================= Expenses ==================")
print("Date".ljust(12), "Description".ljust(12), "Type".ljust(12),"Check Number".ljust(12), "Amount".ljust(12), "Balance".ljust(12))
total = 0
for e in expenses:
print(str(e['date']).ljust(12), str(e['description']).ljust(12), str(e['exptype']).ljust(12), str(e['checkNum']).ljust(12), str(e['amount']).ljust(12))
total = total + e['amount']
print()
print("Total: ", "$%0.2f" % total)
def Main():
expenses = readExpenses("expenses.txt")
printExpenses(expenses)
if __name__ == '__main__':
Main()
Is there a reason you're avoiding creating some objects to manage this? If it were me, I'd go objects and do something like the following (this is completely untested, there may be typos):
#!/usr/bin/env python3
from datetime import datetime # why python guys, do you make me write code like this??
from operator import itemgetter
class BudgetCategory(object):
def __init__(self, name, allowance):
super().__init__()
self.name = name # string naming this category, e.g. 'Food'
self.allowance = allowance # e.g. 400.00 this month for Food
self.expenditures = [] # initially empty list of expenditures you've made
def spend(self, amount, when=None, description=None):
''' Use this to add expenditures to your budget category'''
timeOfExpenditure = datetime.utcnow() if when is None else when #optional argument for time of expenditure
record = (amount, timeOfExpenditure, '' if description is None else description) # a named tuple would be better here...
self.expenditures.append(record) # add to list of expenditures
self.expenditures.sort(key=itemgetter(1)) # keep them sorted by date for the fun of it
# Very tempting to the turn both of the following into #property decorated functions, but let's swallow only so much today, huh?
def totalSpent(self):
return sum(t[0] for t in self.expenditures)
def balance(self):
return self.allowance - self.totalSpent()
Now I can right code that looks like:
budget = BudgetCategory(name='Food', allowance=200)
budget.spend(5)
budget.spend(8)
print('total spent:', budget.totalSpent())
print('left to go:', budget.balance())
This is just a starting point. Now you can you add methods that group (and sum) the expenditures list by decoration (e.g. "I spent HOW MUCH on Twinkies last month???"). You can add a method that parses entries from a file, or emits them to a csv list. You can do some charting based on time.
I'm trying to complete a Project that will show total annual sales from an specific list contained in a .txt file.
The list is formatted this way:
-lastname, firstname (string)
-45.7 (float)
-456.4 (float)
-345.5 (float)
-lastname2, firstname2 (string)
-3354.7 (float)
-54.6 (float)
-56.2 (float)
-lastname3, firstname3 (string)
-76.6 (float)
-34.2 (float)
-48.2 (float)
And so on.... Actually, 7 different "employees" followed by 12 set of "numbers" (months of the year)....but that example should suffice to give an idea of what I'm trying to do.
I need to output this specific information of every "employee"
-Name of employee
-Total Sum (sum of the 12 numbers in the list)
So my logic is taking me to this conclusion, but I don't know where to start:
Create 7 different arrays to store each "employee" data.
With this logic, I need to split the main list into independent arrays so I can work with them.
How can this be achieved? And also, if I don't have a predefined number of employees (but a defined format :: "Name" followed by 12 months of numbers)...how can I achieve this?
I'm sure I can figure once I get an idea how to "split" a list in different sections -- Every 13 lines?
Yes, at every thirteenth line you'd have the information of an employee.
However, instead of using twelve different lists, you can use a dictionary of lists, so that you wouldn't have to worry about the number of employees.
And you can either use a parameter on the number of lines directed to each employee.
You could do the following:
infile = open("file.txt", "rt")
employee = dict()
name = infile.readline().strip()
while name:
employee[name] = list()
for i in xrange(1, 12):
val = float(infile.readline().strip())
employee[name].append(val)
name = infile.readline().strip()
Some ways to access dictionary entries:
for name, months in employee.items():
print name
print months
for name in employee.keys():
print name
print employee[name]
for months in employee.values():
print months
for name, months in (employee.keys(), employee.values()):
print name
print months
The entire process goes as follows:
infile = open("file.txt", "rt")
employee = dict()
name = infile.readline().strip()
while name:
val = 0.0
for i in xrange(1, 12):
val += float(infile.readline().strip())
employee[name] = val
print ">>> Employee:", name, " -- salary:", str(employee[name])
name = infile.readline().strip()
Sorry for being round the bush, somehow (:
Here is option.
Not good, but still brute option.
summed = 0
with open("file.txt", "rt") as f:
print f.readline() # We print first line (first man)
for line in f:
# then we suppose every line is float.
try:
# convert to float
value = float(line.strip())
# add to sum
summed += value
# If it does not convert, then it is next person
except ValueError:
# print sum for previous person
print summed
# print new name
print line
# reset sum
summed = 0
# on end of file there is no errors, so we print lst result
print summed
since you need more flexibility, there is another option:
data = {} # dict: list of all values for person by person name
with open("file.txt", "rt") as f:
data_key = f.readline() # We remember first line (first man)
data[data_key] = [] # empty list of values
for line in f:
# then we suppose every line is float.
try:
# convert to float
value = float(line.strip())
# add to data
data[data_key].append(value)
# If it does not convert, then it is next person
except ValueError:
# next person's name
data_key = line
# new list
data[data_key] = []
Q: let's say that I want to print a '2% bonus' to employees that made more than 7000 in total sales (12 months)
for employee, stats in data.iteritems():
if sum(stats) > 7000:
print employee + " done 7000 in total sales! need 2% bonus"
I would not create 7 different arrays. I would create some sort of data structure to hold all the relevant information for one employee in one data type (this is python, but surely you can create data structures in python as well).
Then, as you process the data for each employee, all you have to do is iterate over one array of employee data elements. That way, it's much easier to keep track of the indices of the data (or maybe even eliminates the need to!).
This is especially helpful if you want to sort the data somehow. That way, you'd only have to sort one array instead of 7.
I have data consisting of about 10,000 entries. Each row is a price for a product in a specific currency. For example:
- Purchase 1 = 10.25 USD
- Purchase 2 = 11.76 SEK
I have ten different database columns to total sales for each currency (this is a requirement). The columns are earnings_in_usd, earnings_in_sek, earnings_in_eur, etc. In my function to do an insert statement to the database, I need to define the necessary variable. By default all other entries will be 0.00. This is basically the code that would accomplish what I need to do:
if currency == 'USD':
earnings_in_usd = value
elif currency == 'SEK':
earnings_in_sek = value
elif ...
Is there a more straightforward way to do this (a way do to something like earnings_in_$ = value)?
Use a defaultdict indexed by the currency.
from collections import defaultdict
earnings = defaultdict(float) # float has a default value of 0.
Instead of your long if-then-else, use this single line:
earnings[currency] = value
and retrieve the earnings in, say, US$, with
earnings["USD"]
Perhaps use a dictionary?
earnings = {}
earnings[currency] = value
One way to do it, which may very well have someone confounded when it breaks, is to use a list comprehension:
earnings_in_usd, earnings_in_sek, ... = [(value if currency == c else 0) for c in CURRENCIES]
The drawback is that the left hand side would have to include all your variables, and CURRENCIES would have to be a list of string constants with exactly the same order as the variables on the left hand side. Like I said, this may very well break if you tamper with other parts of the program...
If earnings is an object/array then
earnings[currency] = value
or
earnings.currency = value;