Как узнать индексы значений в коллекции


person blaughli    schedule 10.11.2011    source источник


Ответы (2)


Если у вас есть список вещей, например:

def list = [ 'c', 'a', 'b' ]

Один из способов узнать исходный индекс — использовать transpose() для присоединения этого списка к счетчику, затем отсортировать новый список, после чего у вас будет отсортированный список с исходным индексом в качестве вторичного элемента.

ie:

[list,0..<list.size()].transpose().sort { it[0] }.each { item, index ->
  println "$item (was at position $index)"
}

Чтобы сломать это;

[list,0..<list.size()]

дает нам (фактически) новый список [ [ 'c', 'a', 'b' ], [ 0, 1, 2 ] ]

вызов transpose() дает нам: [ [ 'c', 0 ], [ 'a', 1 ], [ 'b', 2 ] ]

Затем мы сортируем список на основе первого элемента в каждом элементе (буквы из нашего исходного списка) с помощью sort { it[0] }

И затем перебираем каждый, распечатывая наш теперь отсортированный элемент и его исходное положение индекса.

person tim_yates    schedule 10.11.2011
comment
Спасибо, Тим, я очень ценю твое объяснение. Вы помогаете мне учиться, я не могу передать вам, как здорово получить нервный срыв. Я не буду просто копировать и вставлять (после ПОПЫТКИ выяснить код); вы даете понимание и настраиваете меня на использование этих концепций в будущем. Научите человека ловить рыбу... - person blaughli; 11.11.2011
comment
Как всегда отличный ответ :). Тем не менее, я думаю, что трюк с транспонированием может быть слишком умным. collect со счетчиком тоже может творить чудеса: def i = 0; list.collect { [it, i++] } и, возможно, его проще понять. inject также может это сделать и не требует дополнительного оператора, но я думаю, что это не так красиво. Жаль, что collect не принимает замыкание с элементом и индексом (пока) или что нет Python-подобного enumerate. - person epidemian; 11.11.2011
comment
@epidemian Привет! Я полностью согласен с тем, что использовать внешнюю переменную-счетчик легче для чтения, но с тех пор, как я начал заниматься более функциональным программированием, я старался максимально избегать определения явных переменных. Хотя, может быть, часть моего программистского мозга была сломана изучением Clojure ;-) - person tim_yates; 11.11.2011
comment
@tim_yates Да, по иронии судьбы функциональное программирование может иметь побочный эффект в нашем мозгу, хе-хе. Мне тоже это нравится. Возможно, если бы я использовал этот подход, я бы добавил метод enumerate к List, чтобы получить список пар (индекс, значение), таких как эквивалент Python. Ваше здоровье. - person epidemian; 11.11.2011

Если значения уникальны, вы можете просто использовать метод indexof для исходного списка. Например, если у вас есть список:

def list = [4, 8, 0, 2, 9, 5, 7, 3, 6, 1]

И вы знаете, как получить 5 самых больших значений:

def maxVals = list.sort(false, {-it}).take 5 // This list will be [9, 8, 7, 6, 5]

Затем вы можете сделать:

def indexes = maxVals.collect { list.indexOf it }
println indexes

И он напечатает:

[4, 1, 6, 8, 5]
person epidemian    schedule 11.11.2011
comment
Можете ли вы описать, что делает ваша вторая строка кода, пожалуйста? def maxVals... - person blaughli; 15.11.2011
comment
@blaughli Конечно! Я использую метод sort(boolean mutate, Closure closure). Передача false в качестве первого параметра предотвращает изменение исходного списка методом сортировки; вместо этого он возвращает новый отсортированный список. Второй параметр — это замыкание, которое возвращает значение для сравнения в методе сортировки. В этом случае передача замыкания {-it} отсортирует список в порядке убывания. Вся строка эквивалентна def maxVals = list.clone().sort().reverse().take(5) - person epidemian; 15.11.2011
comment
Я думаю, что наиболее читаемой формой может быть def maxVals = list.sort(false).reverse().take(5). - person epidemian; 15.11.2011
comment
Красиво, большое спасибо! Ребята, вы хорошо учились в школе? Или только с практикой? - person blaughli; 15.11.2011
comment
@blaughli Это немного не по теме, и наверняка будут хорошие статьи о том, как стать лучше в программировании, если вы погуглите их. Я могу говорить только о своем опыте, я думаю. Несколько лет в университете очень помогли мне обрести дисциплину в выполнении дел и изучении новых вещей. Но я думаю, что разница заключается в том, чтобы всегда искать лучшие способы делать вещи (например, спрашивать или искать ответы в StackOverflow =D); как на работе, так и при выполнении домашних заданий для университета обычно не требуется, чтобы вы писали хороший код, поэтому вам решать, заботиться об этом или нет. Ваше здоровье! - person epidemian; 16.11.2011