Инструкция eachWithIndex groovy
Я новичок в groovy, и я столкнулся с некоторыми проблемами, понимающими инструкции each{}
и eachwithindex{}
в groovy.
Действительно ли методы each
и eachWithIndex
? Если да, то какие аргументы они берут?
В документации groovy приведен этот пример:
def numbers = [ 5, 7, 9, 12 ]
numbers.eachWithIndex{ num, idx -> println "$idx: $num" } //prints each index and number
Ну, я вижу, что numbers
- это массив. Что такое num
и idx
в приведенном выше утверждении? Что делает оператор ->
?
Я знаю, что $idx
и $num
печатает значение, но как это связано с тем, что idx
и num
автоматически связаны с индексом и содержимым массива? Какова логика этого? Пожалуйста, помогите.
Ответы
Ответ 1
Это простые методы, но они следуют довольно конкретному шаблону - они принимают Closure
в качестве своего последнего аргумента. Закрытие - это часть функциональности, которую вы можете обойти и вызвать, когда это применимо.
Например, метод eachWithIndex может выглядеть примерно так:
void eachWithIndex(Closure operation) {
for (int i = 0; this.hasNext(); i++) {
operation(this.next(), i); // Here closure passed as parameter is being called
}
}
Этот подход позволяет строить общие алгоритмы (например, итерации по элементам) и изменять конкретную логику обработки во время выполнения, передавая разные блокировки.
Что касается части параметров, как вы видите в примере выше, мы вызываем замыкание (operation
) двумя параметрами - текущим элементом и текущим индексом. Это означает, что каждый метод whithIndex ожидает получить не только закрытие, но и тот, который будет принимать эти два параметра. Из проспективного синтаксиса определяются параметры во время определения закрытия следующим образом:
{ elem, index ->
// logic
}
Итак, ->
используется для разделения аргументов части определения закрытия из его логики. Когда замыкание принимает только один аргумент, его определение параметра может быть опущено, а затем параметр будет доступен в пределах области закрытия с именем it
(неявное имя для первого аргумента). Например:
[1,2,3].each {
println it
}
Его можно было бы переписать следующим образом:
[1,2,3].each({ elem ->
println elem
})
Как вы видите, язык Groovy добавляет некоторый синтаксический сахар, чтобы сделать такие конструкции более красивыми.
Ответ 2
each
и eachWithIndex
, среди многих других, принимают так называемый Closure
как аргумент. Закрытие - это всего лишь фрагмент кода Groovy, заключенный в скобки {}
. В коде с массивом:
def numbers = [ 5, 7, 9, 12 ]
numbers.eachWithIndex{ num, idx -> println "$idx: $num" }
существует только один аргумент (замыкание или, точнее, функция), обратите внимание, что в Groovy ()
скобки иногда бывают необязательными. num
и idx
являются просто необязательными псевдонимами для аргументов закрытия (функции), когда нам нужен только один аргумент, это эквивалентно (it
- неявное имя первого аргумента закрытия, очень удобно):
def numbers = [ 5, 7, 9, 12 ]
numbers.each {println "$it" }
Литература:
Ответ 3
Обычно, если вы используете функциональный язык программирования, например Groovy, вам следует избегать использования each
и eachWithIndex
, поскольку они побуждают вас изменять состояние в закрытии или делать вещи, которые имеют побочные эффекты.
Если возможно, вы можете выполнять свои операции с использованием других методов сбора данных groovy, таких как .collect
или .inject
или findResult
и т.д.
Однако, чтобы использовать их для своей проблемы, то есть распечатать элементы списка с их индексом, вам нужно будет использовать метод withIndex
в исходной коллекции, который преобразует коллекцию в коллекцию пар [element, index ]
Например,
println(['a', 'b', 'c'].withIndex())
Ответ 4
EachWithIndex
можно использовать следующим образом:
package json
import groovy.json.*
import com.eviware.soapui.support.XmlHolder
def project = testRunner.testCase.testSuite.project
def testCase = testRunner.testCase;
def strArray = new String[200]
//Response for a step you want the json from
def response = context.expand('${Offers#Response#$[\'Data\']}').toString()
def json = new JsonSlurper().parseText(response)
//Value you want to compare with in your array
def offername = project.getPropertyValue("Offername")
log.info(offername)
Boolean flagpresent = false
Boolean flagnotpresent = false
strArray = json.Name
def id = 0;
//To find the offername in the array of offers displayed
strArray.eachWithIndex
{
name, index ->
if("${name}" != offername)
{
flagnotpresent= false;
}
else
{
id = "${index}";
flagpresent = true;
log.info("${index}.${name}")
log.info(id)
}
}