1

我有收藏

def list = [4,1,1,1,3,5,1,1]

我需要删除连续重复三次的数字。结果我必须得到一个[4,3,5,1,1]。如何在 groovy 中做到这一点?

4

3 回答 3

1

This can be done by copying the list while ensuring the two previous elements are not the same as the one to be copied. If they are, drop the two previous elements, otherwise copy as normal.

This can be implemented with inject like this:

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]
于 2012-12-17T19:20:35.397 回答
0

另一种选择是使用运行长度编码

首先让我们定义一个类来保存我们的对象以及它连续出现的次数:

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 的方法:

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 ]
于 2012-12-18T10:31:45.657 回答
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
}
于 2012-12-17T19:39:01.367 回答