我有收藏品
def list = [4,1,1,1,3,5,1,1]
我需要删除连续重复三次的数字。结果我得到[4,3,5,1,1]。如何在groovy中做到这一点?
答案 0 :(得分:1)
这可以通过复制列表来完成,同时确保前两个元素与要复制的元素不同。如果是,则删除前两个元素,否则正常复制。
这可以通过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]
答案 1 :(得分:0)
您可以计算接下来三个元素中的唯一身份大小,并在它们为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
}
答案 2 :(得分:0)
另一种选择是使用Run Length Encoding
首先让我们定义一个类来保存我们的对象及其在一行中出现的次数:
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)" }
}
然后我们可以定义一个方法,将List编码为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 )
使用Groovy find方法过滤此RleUnit列表:
// 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 ]