I'm trying to sort the imported data from an XML, then slicing it to take the first 10 and returning it to the my_func dictionary to then print out the rows of data from the key being called by the for loop
from helper import fixNumber
import xml.etree.cElementTree as ET
tree = ET.parse("properties.xml")
root = tree.getroot()
list = []
for child in root:
data = child.attrib.copy()
data['netIncome'] = fixNumber(child.text)
data["id"] = (data["id"])
data['cost'] = fixNumber(data['cost'])
data['downPayment'] = fixNumber(data['downPayment'])
data['state'] = (data['state'])
data['percentage'] = fixNumber(data['percentage'])
list.append(data)
def top_ten(data): # sort top ten by cost in descending order
return data['cost']
list.sort(key=top_ten, reverse=True)
for x in list[:10]:
print(x)
if __name__ == '__main__':
my_func = {
1: top_ten
}
for key in my_func:
funct = my_func[key]
print(f"{key}", funct())
This is the TypeError I keep getting
Traceback (most recent call last):
File "/Users/school/VisualStudio/01.LESSON/properties.py", line 40, in <module>
print(f"{key}", funct())
TypeError: top_ten() missing 1 required positional argument: 'data'
when I type data inside the parathesis of funct, it only prints one data point of an attribute ie. 1 144000.0 which is just one net income from the data
I need to print out the first 10 rows of all the attributes with all the data, sorted. hope this makes sense.
This is a sample of the properties.xml file
<properties>
<property id="H00001" cost="106000" downPayment="24380" state="NM" percentage="0.12">2925.6</property>
<property id="H00002" cost="125000" downPayment="30000" state="AZ" percentage="0.15">4500</property>
<property id="H00003" cost="119000" downPayment="24990" state="NH" percentage="0.13">3248.7</property>
<property id="H00004" cost="124000" downPayment="31000" state="MI" percentage="0.19">5890</property>
<property id="H00005" cost="143000" downPayment="34320" state="CZ" percentage="0.11">3775.2</property>
<property id="H00006" cost="139000" downPayment="30580" state="VI" percentage="0.12">3669.6</property>
<property id="H00007" cost="132000" downPayment="26400" state="ND" percentage="0.19">5016</property>
<property id="H00008" cost="134000" downPayment="26800" state="CZ" percentage="0.17">4556</property>
<property id="H00009" cost="143000" downPayment="34320" state="PA" percentage="0.14">4804.8</property>
<property id="H00010" cost="123000" downPayment="25830" state="IN" percentage="0.2">5166</property>
</properties>
the output should look like this but sorted by cost
1 {'id': 'H00012', 'cost': 150000.0, 'downPayment': 36000.0, 'state': 'OR', 'percentage': 0.11, 'netIncome': 3960.0}
{'id': 'H00061', 'cost': 150000.0, 'downPayment': 34500.0, 'state': 'MD', 'percentage': 0.1, 'netIncome': 3450.0}
{'id': 'H00072', 'cost': 150000.0, 'downPayment': 31500.0, 'state': 'MI', 'percentage': 0.15, 'netIncome': 4725.0}
2 {'id': 'H00012', 'cost': 150000.0, 'downPayment': 36000.0, 'state': 'OR', 'percentage': 0.11, 'netIncome': 3960.0}
{'id': 'H00061', 'cost': 150000.0, 'downPayment': 34500.0, 'state': 'MD', 'percentage': 0.1, 'netIncome': 3450.0}
{'id': 'H00072', 'cost': 150000.0, 'downPayment': 31500.0, 'state': 'MI', 'percentage': 0.15, 'netIncome': 4725.0}
CodePudding user response:
There are a few things to improve in your code, but jumping straight to the solution, you need to adjust these things:
- Your sorting function
def top_ten(ys): # sort top ten by cost in descending order
# sort the list of dicts by desc order
sorted_list = sorted(ys, key=lambda d: -d['cost'])
# print first 10 elements
for elem in sorted_list[:10]:
print(elem)
- Your main call should be like
if __name__ == '__main__':
my_func = {
1: top_ten
}
for key in my_func:
funct = my_func[key]
print(f"{key}", funct(list))
With these changes you should get this output
1:
{'id': 'H00005', 'cost': 143000.0, 'downPayment': 34320.0, 'state': 'CZ', 'percentage': 0.11, 'netIncome': 3775.2}
{'id': 'H00009', 'cost': 143000.0, 'downPayment': 34320.0, 'state': 'PA', 'percentage': 0.14, 'netIncome': 4804.8}
{'id': 'H00006', 'cost': 139000.0, 'downPayment': 30580.0, 'state': 'VI', 'percentage': 0.12, 'netIncome': 3669.6}
{'id': 'H00008', 'cost': 134000.0, 'downPayment': 26800.0, 'state': 'CZ', 'percentage': 0.17, 'netIncome': 4556.0}
{'id': 'H00007', 'cost': 132000.0, 'downPayment': 26400.0, 'state': 'ND', 'percentage': 0.19, 'netIncome': 5016.0}
{'id': 'H00002', 'cost': 125000.0, 'downPayment': 30000.0, 'state': 'AZ', 'percentage': 0.15, 'netIncome': 4500.0}
{'id': 'H00004', 'cost': 124000.0, 'downPayment': 31000.0, 'state': 'MI', 'percentage': 0.19, 'netIncome': 5890.0}
{'id': 'H00010', 'cost': 123000.0, 'downPayment': 25830.0, 'state': 'IN', 'percentage': 0.2, 'netIncome': 5166.0}
{'id': 'H00003', 'cost': 119000.0, 'downPayment': 24990.0, 'state': 'NH', 'percentage': 0.13, 'netIncome': 3248.7}
{'id': 'H00001', 'cost': 106000.0, 'downPayment': 24380.0, 'state': 'NM', 'percentage': 0.12, 'netIncome': 2925.6}
An even cleaner version of your code:
import xml.etree.cElementTree as ET
def load_data(fpath="properties.xml"):
tree = ET.parse(fpath)
root = tree.getroot()
xs = []
for child in root:
data = child.attrib.copy()
data['netIncome'] = float(child.text)
data["id"] = data["id"]
data['cost'] = float(data['cost'])
data['downPayment'] = float(data['downPayment'])
data['state'] = data['state']
data['percentage'] = float(data['percentage'])
xs.append(data)
return xs
def top_ten(ys): # sort top ten by cost in descending order
sorted_list = sorted(ys, key=lambda d: -d['cost'])
for elem in sorted_list[:10]:
print(elem)
def get_avg_netincome(xs):
c = 0
for x in xs:
c = x['netIncome']
print(f'Average net income: {round(c / len(xs), 2)}')
if __name__ == '__main__':
my_func = {
1: top_ten,
2: get_avg_netincome,
}
for funct_id, funct in my_func.items():
print(f'Function id: {funct_id}')
data = load_data()
funct(data)
print()
Which produces the same output:
Function id: 1
{'id': 'H00005', 'cost': 143000.0, 'downPayment': 34320.0, 'state': 'CZ', 'percentage': 0.11, 'netIncome': 3775.2}
{'id': 'H00009', 'cost': 143000.0, 'downPayment': 34320.0, 'state': 'PA', 'percentage': 0.14, 'netIncome': 4804.8}
{'id': 'H00006', 'cost': 139000.0, 'downPayment': 30580.0, 'state': 'VI', 'percentage': 0.12, 'netIncome': 3669.6}
{'id': 'H00008', 'cost': 134000.0, 'downPayment': 26800.0, 'state': 'CZ', 'percentage': 0.17, 'netIncome': 4556.0}
{'id': 'H00007', 'cost': 132000.0, 'downPayment': 26400.0, 'state': 'ND', 'percentage': 0.19, 'netIncome': 5016.0}
{'id': 'H00002', 'cost': 125000.0, 'downPayment': 30000.0, 'state': 'AZ', 'percentage': 0.15, 'netIncome': 4500.0}
{'id': 'H00004', 'cost': 124000.0, 'downPayment': 31000.0, 'state': 'MI', 'percentage': 0.19, 'netIncome': 5890.0}
{'id': 'H00010', 'cost': 123000.0, 'downPayment': 25830.0, 'state': 'IN', 'percentage': 0.2, 'netIncome': 5166.0}
{'id': 'H00003', 'cost': 119000.0, 'downPayment': 24990.0, 'state': 'NH', 'percentage': 0.13, 'netIncome': 3248.7}
{'id': 'H00001', 'cost': 106000.0, 'downPayment': 24380.0, 'state': 'NM', 'percentage': 0.12, 'netIncome': 2925.6}
Function id: 2
Average net income: 4355.19