简体   繁体   English

Python function 根据嵌套字典中的字符串值对 integer 值求和?

[英]Python function to sum integer values based on string values in a nested dictionary?

The following is a subset of the data that I have:以下是我拥有的数据的子集:

VALID_CAR_NAMES = ['Audi', 'Holden', 'Honda', 'Mitsubishi', 'Toyota', 'Volvo']

car_data = {
    '1': {'Name': 'Emily', 'CarName': 'Toyota', 'Price': '1000'},
    '2': {'Name': 'John', 'CarName': 'Audi', 'Price': '30000'},
    '3': {'Name': 'Ben', 'CarName': 'Audi', 'Price': '35000'},
    '4': {'Name': 'Jasmine', 'CarName': 'Holden', 'Price': '17000'},
    '5': {'Name': 'Tara', 'CarName': 'Mitsubishi', 'Price': '1000'},
    '6': {'Name': 'Kristy', 'CarName': 'Mitsubishi', 'Price': '1500'},
    '7': {'Name': 'Eddy', 'CarName': 'Honda', 'Price': '2000'},
    '8': {'Name': 'Brett', 'CarName': 'Honda', 'Price': '2500'}
}

Here I'm trying to find the sum of the price column for each car in the list VALID_CAR_NAMES.在这里,我试图找到列表 VALID_CAR_NAMES 中每辆车的价格列的总和。 And if there is no data for a car in VALID_CAR_NAMES, the sum will be None.如果 VALID_CAR_NAMES 中没有汽车的数据,则总和将为 None。

The output should look like this (eg here the sum for Volvo is None because there's no data for it in the input dictionary car_data): output 应该如下所示(例如,这里沃尔沃的总和为 None,因为输入字典 car_data 中没有它的数据):

{
    'Audi': {'sum': 65000}, 
    'Holden': {'sum': 17000}, 
    'Honda': {'sum': 4500}, 
    'Mitsubishi': {'sum': 2500}, 
    'Toyota': {'sum': 1000}, 
    'Volvo': {'sum': None}
}

So here's a function that I've tried to write.所以这是我尝试编写的 function。 If I get rid of the else statement, it will sum up the prices for each car.如果我去掉 else 语句,它将总结每辆车的价格。 But when I run the code with the else statement (to change the 0 into None for cars with missing/no data), I end up getting "TypeError: unsupported operand type(s) for +=: 'NoneType' and 'int'".但是,当我使用 else 语句运行代码时(对于缺少/没有数据的汽车,将 0 更改为 None),我最终得到“TypeError: unsupported operand type(s) for +=: 'NoneType' and 'int' ”。 This leads me to think my approach is wrong...这让我觉得我的方法是错误的......

def sum_car_price(car_data):
    sum_car_price_dict = {'Toyota': {'sum': 0}, 'Audi': {'sum': 0}, 'Holden': {'sum': 0},\
                      'Mitsubishi': {'sum': 0}, 'Honda': {'sum': 0}, 'Volvo': {'sum': 0}}
    for car_id, customer_data in car_data.items():
        for car_name, car_price in sum_car_price_dict.items():
            if customer_data['CarName'] in car_name:
                car_price['sum'] += int(customer_data['Price'])
            else:
                car_price['sum'] = None
    return sum_car_price_dict

You gotta love lambdas, generators and list comprehensions:你必须喜欢 lambdas、生成器和列表推导:

prices = lambda c: (int(cd["Price"]) for cd in car_data.values() if cd["CarName"] == c)
x = {c: {"sum": sum(prices(c)) or None} for c in VALID_CAR_NAMES}
def sum_car_price(car_data):
    """This function takes a dictionary of clean data (car_data) and
    finds the sum total price for each car in the list VALID_CAR_NAMES.
    The return value is a dict with the sum price for each car"""

    sum_car_price_dict = {'Toyota': {'sum': None}, 'Audi': {'sum': None}, 'Holden': {'sum': None}, 'Mitsubishi': {'sum': None}, 'Honda': {'sum': None}, 'Volvo': {'sum': None}}

    for car_id, customer_data in car_data.items():
        if customer_data['CarName'] in VALID_CAR_NAMES:
            if sum_car_price_dict[customer_data['CarName']]['sum'] == None:
                sum_car_price_dict[customer_data['CarName']]['sum'] = customer_data['Price']
            else:
                sum_car_price_dict[customer_data['CarName']]['sum'] += customer_data['Price']

    return sum_car_price_dict

You could just pre-initialize the dictionary with None values beforehand, and then simply check if it is already None, and act accordingly.您可以预先使用 None 值预先初始化字典,然后简单地检查它是否已经是 None,并采取相应的行动。

how about this?这个怎么样?

def sum_car_price(car_data):
        result = {}
        for car in VALID_CAR_NAMES:
            data = [int(c["Price"]) for c in car_data.values() if c["CarName"]==car]
            result[car] = {"sum":sum(data ) if data else None}
        return result
def sum_car_price(car_data):
    """
    This function takes a dictionary of clean data (car_data) and 
    finds the sum total price for each car in the list VALID_CAR_NAMES.
    The return value is a dict with the sum price for each car
    """

    # initialize all valid cars' count to 0
    sum_car_price_dict = dict( (key, {'sum': 0}) for key in VALID_CAR_NAMES)

    # iterate through all the data
    for car_id, customer_data in car_data.items():
        car_name = customer_data['CarName'] 
        if car_name in VALID_CAR_NAMES:
            try:
                sum_car_price_dict[car_name]['sum'] += int(customer_data['Price'])
            except KeyError:
                pass

    for value in sum_car_price_dict.values():
        if value['sum'] == 0:
            value['sum'] = None

    return sum_car_price_dict

The problem is, you should not directly add an int to None in mid-way.问题是,您不应该在中途直接将int添加到None

Considering your requirement, this should work.考虑到您的要求,这应该可行。 Main reason for the error is your order of nesting the for loops.错误的主要原因是您嵌套 for 循环的顺序。

for car_name, car_price in sum_car_price_dict.items():
    for car_id, customer_data in car_data.items():
        if customer_data['CarName'] == car_name:
            car_price['sum'] += int(customer_data['Price'])
    if (car_price['sum'] == 0):
        car_price['sum'] = None

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM