我可以根据两个值将列表理解缩减为两个列表吗?

时间:2010-12-27 15:28:39

标签: python python-2.5

我有以下代码。

sum_review = reduce(add,[book['rw'] for book in books])
sum_rating = reduce(add,[book['rg'] for book in books])
items = len(books)
avg_review = sum_review/items
avg_rating = sum_rating/items

我想要的是这个。

sum_review,sum_rating = reduce(add,([book['rw'],[book['rg']) for book in books])
items = len(books)
avg_review = sum_review/items
avg_rating = sum_rating/items

显然这不起作用。如果没有常规循环,我怎样才能解决这种冗余?

5 个答案:

答案 0 :(得分:9)

我在这里避免使用reduce。对于这么简单的使用sum

sum_review = sum(book['rw'] for book in books)
sum_rating = sum(book['rg'] for book in books)

在我看来,这个更简单的版本不需要重构来删除冗余。只有两个项目(rwrg)我认为最好保持原样。

答案 1 :(得分:3)

有两种简化代码的典型方法:

  1. 自上而下:首先获取值,然后使用zip(*iterable)转置它们。它也很酷,因为它只迭代集合一次:

    values = ((book["rw"], book["rg"]) for book in books)
    avg_review, avg_rating = [sum(xs) / len(books) for xs in zip(*values)]
    
  2. 自下而上:创建一个抽象操作的函数:

    get_avg = lambda xs, attr: sum(x[attr] for x in xs) / len(xs)
    avg_review = get_avg(books, "rw")
    avg_rating = get_avg(books, "rg")
    

答案 2 :(得分:2)

您应该优先考虑清晰度而不是优化。在使用Python的3年中,我只需要分析两次发现性能瓶颈。您的原始代码清晰有效。将前两行压缩为一个会损害可读性并且几乎不会影响性能。

如果我来修改你的代码,它会这样:

avg_review = sum(book['rw'] for book in books) / len(books)
avg_rating = sum(book['rg'] for book in books) / len(books)

(这是五行代码,一到两行,提高了清晰度。)

答案 3 :(得分:1)

sum_review, sum_rating = reduce(lambda a,b: (a[0] + b[0], a[1]+b[1]), ((book['rw'], book['rg']) for book in books), (0,0) )
items = len(books)
avg_review = sum_review/items
avg_rating = sum_rating/items

(测试)

答案 4 :(得分:1)

  

如何解决此冗余问题

通过制作一个功能,当然:

def average_value(items, key):
  values = [x[key] for x in items]
  return sum(items) / len(items)

avg_review, avg_rating = average_value(books, 'rw'), average_value(books, 'rg')