Выбрать элементы по (un) четному индексу из массива в Groovy - PullRequest
1 голос
/ 06 ноября 2019

У меня есть массив Groovy, содержащий цифры числа. Мне нужно создать два новых массива, содержащих только цифры в четных соотношениях. неровные позиции из этого массива.

Лучший способ найти это, но я чувствую, что здесь есть много возможностей для улучшения:

def evenDigits = digits
    .indexed(1)
    .findAll { i, v -> i % 2 == 0 }
    .collect { it.value }

Очевидно, вариант unevenDigitsбыло бы просто проверить модуль в закрытии findAll против 1 вместо 0.

Кто-нибудь знает, может ли этот код быть улучшен или сжат?

Ответы [ 5 ]

4 голосов
/ 06 ноября 2019

«менее умное» (и определенно более производительное) решение:

def evens = [], odds = []
digits.eachWithIndex{ v, ix -> ( ix & 1 ? odds : evens ) << v }
3 голосов
/ 06 ноября 2019

Вы можете использовать groupBy для разделения результатов на нечетные / четные элементы. Например,

groovy:000> ["a","b","c"].indexed(1).groupBy{ i, _ -> i & 1 }.collectEntries{ k, v -> [k as Boolean, v.values()] }
===> [true:[a, c], false:[b]]
1 голос
/ 07 ноября 2019

Другим вариантом для одного прохода (но все же с промежуточным сбором из-за indexed) будет сокращение:

def (odd,even) = digits.indexed().inject([[],[]]){ acc, it -> acc[it.key&1] << it.value; acc }
0 голосов
/ 06 ноября 2019

Еще одно решение «Groovy», в котором используется комбинация withIndex() и findResults().

  • withIndex() преобразует List<T> в List<Tuple2<T,Integer>> - список кортежей значений-индексов.
  • findResults(closure) выполняет преобразование фильтрации - полученное закрытие является преобразованиемсказуемое. В нашем случае он проверяет, является ли значение индекса нечетным или четным, и извлекает значение из кортежа, если предикат соответствует. (Все null значения отфильтрованы.)

Кратко и кратко. Требуется минимальное количество преобразований: от List<T> до List<Tuple2<T,Integer>>, а затем одна итерация для получения окончательного результата.

def numbers = [1,2,3,4,5,6,2,3,1] // Some test data

def even = { t -> t.second % 2 == 0 ? t.first : null } // "Even" transforming predicate
def odd = { t -> t.second % 2 == 1 ? t.first : null } // "Odd" transforming predicate

def evens = numbers.withIndex(1).findResults even
def odds = numbers.withIndex(1).findResults odd

// And some assertions to test the implementation
assert evens == [2,4,6,3]
assert odds == [1,3,5,2,1]
0 голосов
/ 06 ноября 2019

Я придумал это, но это, вероятно, не самый умный способ.

    def isEven = { int x -> x % 2 == 0 ? x : null}

    def (digits, evens, odds) = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [], []] 

    digits.each { 
        if (isEven(it))
            evens.add(isEven(it))
    }

    odds = digits - evens 

    assert evens == [2, 4, 6, 8]
    assert odds == [1, 3, 5, 7, 9]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...