2012-12-17 106 views
1

號我有收集刪除其重複幾次連續

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

,我需要刪除其連續重複三次號碼。因此我必須得到[4,3,5,1,1]。如何在groovy中做到這一點?

回答

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] 
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 
} 
+0

我相信你可以使用'list.collat​​e(3,1)'以及 –

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)" } 
} 

然後我們就可以定義將列表編碼爲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 ]