从Groovy中的数组中选择(不)偶数索引上的元素

我有一个Groovy数组,其中包含一个数字。我需要创建两个仅包含偶数位的新数组。该数组的位置不均匀。

我能找到的最好方法是这样,但是我觉得这里还有很大的改进空间:

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

显然,unevenDigits的变种是仅针对findAll而不是1检查0闭包中的模数。

有人知道是否可以改进或压缩此代码?

vi324 回答:从Groovy中的数组中选择(不)偶数索引上的元素

“更聪明”(绝对是性能更高)的解决方案:

def evens = [],odds = []
digits.eachWithIndex{ v,ix -> ( ix & 1 ? odds : evens ) << v }
,

您可以使用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]]
,

对于单次通过(但由于indexed仍具有中间集合)的另一种选择是减少:

def (odd,even) = digits.indexed().inject([[],[]]){ acc,it -> acc[it.key&1] << it.value; acc }
,

我想到了这个,但这可能不是最聪明的方法。

    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,8]
    assert odds == [1,9]
,

另一个使用withIndex()findResults()组合的“ Groovy”解决方案。

  • withIndex()List<T>转换为List<Tuple2<T,Integer>>-值索引元组列表。
  • findResults(closure)运行过滤转换-它收到的闭包是一个转换谓词。在我们的例子中,它检查索引值是奇数还是偶数,如果谓词匹配,则从元组中提取值。 (所有null值都被过滤掉。)

简洁明了。所需的转换次数最少:从List<T>List<Tuple2<T,Integer>>,然后进行一次迭代即可产生最终结果。

def numbers = [1,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,3]
assert odds == [1,1]
本文链接:https://www.f2er.com/3152905.html

大家都在问