Найти сумму подмножеств списка в python

#list #python #chunks

#Список #python #фрагменты

Вопрос:

Вероятно, это очень просто, и я кое-что упускаю из виду…

У меня есть длинный список целых чисел, в данном случае представляющих ежедневных посетителей веб-сайта. Я хочу новый список еженедельных посетителей. Итак, мне нужно получить группы по семь из исходного списка, просуммировать их и добавить в новый список.

Мое решение кажется довольно грубым, неэлегантным:

 numweeks = len(daily) / 7
weekly = []
for x in range(numweeks):
    y = x*7
    weekly.append(sum(visitors[y:y 7]))
  

Есть ли более эффективный или более питонический способ сделать это?

Комментарии:

1. На самом деле это хороший вопрос для codereview.stackexchange.com , которая предназначена специально для улучшения кода, который работает, чтобы сделать его быстрее / элегантнее.

2. Спасибо … не знал об этом сайте stackexchange. Трудно понять, какое из них подходит для какого вопроса, тем более что в наши дни их так много. Кроме того, в этом, кажется, есть все плюсы, поэтому я всегда чувствую, что оригинал лучше. 🙂

3. В этом коде нет ничего плохого — он прост и хорошо передает свои намерения. Я бы просто изменил имена переменных на что-то более описательное, чем x и y , но в остальном это предпочтительнее любого взлома, основанного на понимании

4. Разница в том, что там вы привлекаете внимание именно тех людей, которым нравится читать чужой код, чтобы понять, как сделать что-то лучше.

Ответ №1:

 weekly = [ sum(visitors[x:x 7]) for x in range(0, len(daily), 7)]
  

Или чуть менее плотно:

 weekly = []
for x in range(0, len(daily), 7):
     weekly.append( sum(visitors[x:x 7]) )
  

В качестве альтернативы можно использовать модуль numpy.

 by_week = numpy.reshape(visitors, (7, -1))
weekly = numpy.sum( by_week, axis = 1)
  

Обратите внимание, что для этого требуется, чтобы количество элементов в visitor было кратно 7. Это также требует, чтобы вы установили numpy. Однако, это, вероятно, также более эффективно, чем другие подходы.

Или для itertools бонус к коду:

 def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)

weekly = map(sum, grouper(7, visitors, 0))
  

Комментарии:

1. 1 за включение itertools.izip_longest case, которого, я надеялся, у вас не было, чтобы я мог упомянуть об этом. 🙂

2. Кроме того, для больших наборов посетителей или если visitors является генератором, параметры itertools.izip_longest и itertools.imap более эффективны, и я бы использовал xrange вместо range вызова в первом примере.

Ответ №2:

 >>> daily = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
>>> print [sum(daily[x:x 7]) for x in range(0, len(daily), 7)]
[28, 77, 105]
  

Я не уверен, что это «pythonic», но мне действительно нравится этот однострочный материал python.

Кровавые подробности: Понимания

Ответ №3:

Используя itertools.islice:

 weekly = [sum(list(itertools.islice(daily, i, i 7)))
          for i in range(0, len(daily), 7)]
  

Редактировать:

или с помощью math.fsum:

 weekly = [math.fsum(itertools.islice(daily, i, i 7))
          for i in range(0, len(daily), 7)]
  

Комментарии:

1. Подобное использование islice будет не очень эффективным. Таким образом, вы будете многократно перебирать элементы в daily.