3

我有以下代码。

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

显然这是行不通的。在没有常规循环的情况下,如何解决这种冗余?

4

5 回答 5

9

我会避免在这里使用reduce。对于如此简单的用途sum

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

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

于 2010-12-27T15:33:28.797 回答
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")
    
于 2010-12-27T15:34:10.493 回答
2
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

(已测试)

于 2010-12-27T15:38:24.167 回答
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)

(将五行代码减少到两行,提高了清晰度。)

于 2010-12-27T16:10:09.747 回答
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')
于 2010-12-27T16:14:31.580 回答