PYTHON – поиск максимума из каждых 10 целых чисел в массиве

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

ex. (max_value, index of max_value in array)

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

Я пробовал использовать:

a = some array of integers

split = [a[i:i+10] for i in xrange(0, len(a), 10)] 

for i in split:
    j = max(i) 
    k = i.index(max(i))
    print (j,k)

Проблема с этим методом заключается в том, что он разбивает мой массив на куски по 10, поэтому max_values ​​верны, но индексы неточны (все индексы находятся в диапазоне от 0 до 10). Мне нужно найти способ сделать это, который не t разделить мой массив на куски, чтобы сохранить исходные индексы. Я уверен, что есть более простой способ поиска максимальных значений, но я не могу понять это.


person nikki_c    schedule 01.08.2017    source источник
comment
повторяются ли какие-либо значения в вашем массиве?   -  person depperm    schedule 01.08.2017
comment
индекс может быть рассчитан, если вы добавили enumerate, затем выполните q*10+i, где q - счетчик перечисления   -  person depperm    schedule 01.08.2017


Ответы (8)


Таким образом, при отладке массива примеров мы обнаруживаем, что split возвращает двумерный список, подобный этому:

[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]]

И каждый раз, когда цикл for выполняется, он проходит по одному из этих списков по порядку. Сначала он проходит через первый внутренний список, затем второй и т. д. Поэтому каждый раз, когда цикл for переходит к следующему списку, мы просто добавляем 10. Поскольку в списке может быть более 2 списков, мы сохраняем число, которое нам нужно добавить. в переменной и добавляйте к ней 10 в каждом цикле:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
split = [a[i:i+10] for i in xrange(0, len(a), 10)] 
counter = 0

for i in split:
    j = max(i) 
    k = i.index(max(i))
    print (j,k+counter)
    counter += 10

Вы можете протестировать его здесь

person Anthony Pham    schedule 01.08.2017

Небольшая модификация вашего текущего кода:

a = some array of integers

split = [a[i:i+10] for i in xrange(0, len(a), 10)] 

for index, i in enumerate(split):
    j = max(i) 
    k = i.index(max(i))
    print (j, k+10*index)
person Harald Nordgren    schedule 01.08.2017
comment
кажется, все хотят вычислить j дважды, и каждый раз я немного вздрагиваю :P (в любом случае это не окажет реального влияния...) - person Aaron; 01.08.2017
comment
Чувак, микрооптимизация! Но да, вы должны повторно использовать j в производственном сценарии. Однако здесь, на Stack Overflow, все дело в ясности и знакомстве. :) - person Harald Nordgren; 01.08.2017

Вам нужно подсчитать количество элементов, которые появляются перед текущим окном. Это сделает работу:

a=list(range(5,35))
split = [a[i:i+10] for i in xrange(0, len(a), 10)] 

for ind,i in enumerate(split):
    j = max(i) 
    k = i.index(j)
    print (j,k+ind*10)

Это печатает

(14, 9)
(24, 19)
(34, 29)
person Miriam Farber    schedule 01.08.2017

Пакет toolz имеет файл partition_all, которая делит последовательность на кортежи одинакового размера, поэтому вы можете сделать что-то вроде этого.

import toolz
ns = list(range(25))
[max(sublist) for sublist in toolz.partition_all(10, ns)]

Это вернет [9, 19, 24].

person W.P. McNeill    schedule 01.08.2017

Вам нужно будет выполнить цикл, чтобы просмотреть список, однако мы можем изменить ваш цикл split, чтобы сделать его более эффективным для того, что вы хотите.

a = some array of integers

split = [a[i:i+10] for i in xrange(0, len(a), 10)] 

for i in range(len(split)):
    #Now instead of being the list, i is the index, so we can use 10*i as a counter
    j = max(split[i]) 
    #j = max(i) 
    k = split[i].index(j) + 10*i #replaced max(i) with j since we already calculated it.
    #k = i.index(max(i))
    print (j,k)

Однако в будущем, пожалуйста, создайте новое имя для вашего списка split, так как split уже является функцией в python. Возможно, split_list или separated, или какое-то другое имя, не похожее на функцию split().

person Davy M    schedule 01.08.2017
comment
@dawg нет функции с именем split .. только метод строк, так что не топайте. whatever.split = something_else было бы проблемой, но не это - person Aaron; 01.08.2017

решение numpy для произвольного ввода:

import numpy as np

a = np.random.randint(1,21,40)  #40 random numbers from 1 to 20

b = a.reshape([4,10])  #shape into chunks 10 numbers long

i = b.argsort()[:,-1]  #take the index of the largest number (last number from argsort) 
                       #  from each chunk. (these don't take into account the reshape)

i += np.arange(0,40,10)  #add back in index offsets due to reshape

out = zip(i, a[i])  #zip together indices and values
person Aaron    schedule 01.08.2017

Вы можете упростить это, перечислив только один раз и используя zip для разделения списка на группы:

n=10
for grp in zip(*[iter(enumerate(some_list))]*n):
    grp_max_ind, grp_mv=max(grp, key=lambda t: t[1])
    k=[t[1] for t in grp].index(grp_mv)
    print grp_mv, (grp_max_ind, k)

Используйте izip в Python 2, если вам нужен генератор (или используйте Python 3)

from itertools import izip 
for grp in izip(*[iter(enumerate(some_list))]*n):
    grp_max_ind, grp_mv=max(grp, key=lambda t: t[1])
    k=[t[1] for t in grp].index(grp_mv)
    print grp_mv, (grp_max_ind, k)

Zip обрежет последнюю группу, если ее длина не равна n

person dawg    schedule 01.08.2017

Пример использования numpy. Сначала сгенерируем некоторые данные, то есть целые числа от 1 до V и длиной (количество значений) L:

import numpy as np
V = 1000
L = 45 # method works with arrays not multiples of 10
a = np.random.randint(1, V, size=L)

Теперь решим задачу для подмассивов размера N:

import numpy as np
N = 10 # example "split" size
sa = np.array_split(a, range(N, len(a), N))
sind = [np.argpartition(i, -1)[-1] for i in sa]
ind = [np.ravel_multi_index(i, (len(sa), N)) for i in enumerate(sind)]
vals = np.asarray(a)[np.asarray(ind)]
split_imax = zip(vals, ind) # <-- output
person AGN Gazer    schedule 01.08.2017