代码之家  ›  专栏  ›  技术社区  ›  Mayka

通过带条件的生成器表达式指定两个变量?

  •  3
  • Mayka  · 技术社区  · 6 年前

    下面的代码有一个包含各种奶酪及其数量的字典。根据预先确定的销售项目列表,代码然后打印出在售奶酪的总数量与全价。

    我使用生成器表达式来计算总数,但我想知道是否有一种方法可以压缩我的代码来分配 sale_count full_price_count 同时使用某种if-else条件的变量,因为生成器的代码实际上是相同的。

    cheeses = {'gouda': 3, 'cheddar': 7, 'american': 2, 'mozzarella': 5}
    on_sale = ['american', 'blue cheese', 'cheddar', 'provolone', 'swiss']
    
    # if the cheese is on sale, add its quantity to sale_count
    # otherwise, add its quantity to full_price_count
    sale_count = sum(qty for (cheese, qty) in cheeses.items() if cheese in on_sale)
    full_price_count = sum(qty for (cheese, qty) in cheeses.items() if cheese not in on_sale)
    
    print("Sale count: {}\nFull price count: {}".format(sale_count, full_price_count))
    
    3 回复  |  直到 6 年前
        1
  •  2
  •   donkopotamus    6 年前

    可以在单个表达式中完成,如下所示:

    functools.reduce(
        lambda x, y: (x[0] + y[0], x[1] + y[1]),
        ((qty, 0) if cheese in on_sale else (0, qty) for cheese, qty in cheeses.items()), 
        (0, 0))
    

    但是,就像其他可能的答案一样,这可能真正回答了为什么 当两个表达式完全清楚时,不必总是简化为一个表达式。

        2
  •  0
  •   MegaIng Mischa Lisovyi    6 年前

    另一种方法是如下所示,但我同意@donkopotamus,如果您没有性能问题,wo表达式也可以。

    sale_count, full_price_count  = map(sum, zip(*((v * (c in on_sale), v * (c not in on_sale)) for c, v in cheeses.items())))
    
        3
  •  0
  •   Jundiaius    6 年前

    它的可读性不是很强,但它在一行中实现了您想要的功能:

    [sale_count, full_price_count] = map(sum, zip(*[(qty, 0) if cheese in on_sale else (0, qty) for cheese, qty in cheeses.items()]))