コレクションがあります
def list = [4,1,1,1,3,5,1,1]
そして、3回続けて繰り返される数字を削除する必要があります。その結果、[4,3,5,1,1]を取得する必要があります。Groovyでこれを行う方法は?
コレクションがあります
def list = [4,1,1,1,3,5,1,1]
そして、3回続けて繰り返される数字を削除する必要があります。その結果、[4,3,5,1,1]を取得する必要があります。Groovyでこれを行う方法は?
これは、前の2つの要素がコピーする要素と同じでないことを確認しながら、リストをコピーすることで実行できます。そうである場合は、前の2つの要素を削除します。そうでない場合は、通常どおりにコピーします。
これは、次のように実装できますinject
。
def list = [4,1,1,1,3,5,1,1]
def result = list.drop(2).inject(list.take(2)) { result, element ->
def prefixSize = result.size() - 2
if ([element] * 2 == result.drop(prefixSize)) {
result.take(prefixSize)
} else {
result + element
}
}
assert result == [4,3,5,1,1]
次の3つの要素で一意のサイズを計算し、1のときにそれらを削除できます。
def list = [4,1,1,1,3,5,1,1]
assert removeTriplets(list) == [4,3,5,1,1]
def removeTriplets(list) {
listCopy = [] + list
(list.size()-3).times { index ->
uniques = list[index..(index+2)].unique false
if (uniques.size() == 1)
listCopy = listCopy[0..(index-1)] + listCopy[(index+3)..-1]
}
listCopy
}
別のオプションは、ランレングスエンコーディングを使用することです
まず、オブジェクトを保持するクラスと、オブジェクトが連続して発生する回数を定義しましょう。
class RleUnit {
def object
int runLength
RleUnit( object ) {
this( object, 1 )
}
RleUnit( object, int runLength ) {
this.object = object
this.runLength = runLength
}
RleUnit inc() {
new RleUnit( object, runLength + 1 )
}
String toString() { "$object($runLength)" }
}
次に、リストをRleUnit
オブジェクトのリストにエンコードするメソッドを定義できます。
List<RleUnit> rleEncode( List list ) {
list.inject( [] ) { r, v ->
if( r && r[ -1 ].object == v ) {
r.take( r.size() - 1 ) << r[ -1 ].inc()
}
else {
r << new RleUnit( v )
}
}
}
そして、RleUnit
オブジェクトのリストを取得し、それを元のリストに解凍するメソッド:
List rleDecode( List<RleUnit> rle ) {
rle.inject( [] ) { r, v ->
r.addAll( [ v.object ] * v.runLength )
r
}
}
次に、元のリストをエンコードできます。
def list = [ 4, 1, 1, 1, 3, 5, 1, 1 ]
rle = rleEncode( list )
そして、このRleUnitリストをGroovyfindメソッドでフィルタリングします。
// remove all elements with a runLength of 3
noThrees = rle.findAll { it.runLength != 3 }
unpackNoThrees = rleDecode( noThrees )
assert unpackNoThrees == [ 4, 3, 5, 1, 1 ]
// remove all elements with a runLength of less than 3
threeOrMore = rle.findAll { it.runLength >= 3 }
unpackThreeOrMore = rleDecode( threeOrMore )
assert unpackThreeOrMore == [ 1, 1, 1 ]