Can I make a reduction in understanding a list in two lists based on two values?

I have the following code.

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

I wish it were.

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

Obviously this does not work. How can I solve this redundancy without a regular cycle?

+3
source share
5 answers

There are two typical approaches to simplifying code:

  • From top to bottom: first get the values ​​and then transpose them with zip(*iterable). This is also cool because it only iterates through the collection once:

    values = ((book["rw"], book["rg"]) for book in books)
    avg_review, avg_rating = [sum(xs) / len(books) for xs in zip(*values)]
    
  • Bottom: create a function to abstract the operation:

    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")
    
+3
source

I would not use the abbreviation here. For something so simple to use sum:

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

-, . (rw rg), , .

+9

You should prefer clarity in optimization. For 3 years of using Python, I only had to profile performance bottlenecks. Your source code is clear and efficient. Compressing the first two lines in one degrades readability and barely affects performance.

If I had to revise the code, he would like to:

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

(These are five lines of code to two with improved clarity.)

+2
source
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

(verified)

+1
source

How can I solve this redundancy

Having made, of course, the function:

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')
+1
source

Source: https://habr.com/ru/post/1782303/


All Articles