Skip to main content
Added another solution
Source Link

Or, how about this one?

func FirstSubsliceWithoutAdjacentDuplicates(strings []string) ([]string, int) {
    if len(strings) < 2 {
        return strings, 0
    }
    for i := 1; i < len(strings); i++ {
        if strings[i-1] == strings[i] {
            repeats := 1
            for i+repeats < len(strings) && strings[i] == strings[i+repeats] {
                repeats++
            }
            return strings[:i], repeats
        }
    }
    return strings, 0
}

func RemoveAdjacentDuplicates(toBeProcessed []string) []string {
    unique, repeats := FirstSubsliceWithoutAdjacentDuplicates(toBeProcessed)
    if len(unique) == len(toBeProcessed) {
        return unique
    }
    result := toBeProcessed
    copyTarget := toBeProcessed
    finalLength := 0
    for len(unique) > 0 {
        finalLength += len(unique)
        copy(copyTarget, unique)
        toBeProcessed = toBeProcessed[len(unique)+repeats:]
        copyTarget = copyTarget[len(unique):]
        unique, repeats = FirstSubsliceWithoutAdjacentDuplicates(toBeProcessed)
    }
    return result[0:finalLength]
}

Or, how about this one?

func FirstSubsliceWithoutAdjacentDuplicates(strings []string) ([]string, int) {
    if len(strings) < 2 {
        return strings, 0
    }
    for i := 1; i < len(strings); i++ {
        if strings[i-1] == strings[i] {
            repeats := 1
            for i+repeats < len(strings) && strings[i] == strings[i+repeats] {
                repeats++
            }
            return strings[:i], repeats
        }
    }
    return strings, 0
}

func RemoveAdjacentDuplicates(toBeProcessed []string) []string {
    unique, repeats := FirstSubsliceWithoutAdjacentDuplicates(toBeProcessed)
    if len(unique) == len(toBeProcessed) {
        return unique
    }
    result := toBeProcessed
    copyTarget := toBeProcessed
    finalLength := 0
    for len(unique) > 0 {
        finalLength += len(unique)
        copy(copyTarget, unique)
        toBeProcessed = toBeProcessed[len(unique)+repeats:]
        copyTarget = copyTarget[len(unique):]
        unique, repeats = FirstSubsliceWithoutAdjacentDuplicates(toBeProcessed)
    }
    return result[0:finalLength]
}
Added a maybe better example with comments
Source Link

And here a maybe more efficient one with comments, which copies in chunks with copy A lot of code for a simple task. I don't know if it is really more performant as simpler solutions (regarding code) and I am sure that it can be done easier.

func RemoveAdjacentDuplicates(strings []string) []string {
     // at least two elements need to be in the slice to have adjacent duplicates
     if len(strings) < 2 {
        return strings
    }
    current, nextDifferent, nextDifferentEnd := 0, 1, 0
    for nextDifferentEnd+1 < len(strings) {
        // search for next different element
        for nextDifferent < len(strings) && strings[current] == strings[nextDifferent] {
            nextDifferent++
        }
        // look for the largest subslice from the next different up to the next duplicate
        nextDifferentEnd = nextDifferent + 1
        for nextDifferentEnd < len(strings) && strings[nextDifferentEnd-1] != strings[nextDifferentEnd] {
            nextDifferentEnd++
        }
        // if we did not reach the and of the slice,
        // replace the duplicate(s) with the next subslice with different elements
        if nextDifferent < len(strings) {
            if current+1 != nextDifferent {
                copy(strings[current+1:], strings[nextDifferent:nextDifferentEnd])
            }
            current += nextDifferentEnd - nextDifferent
            nextDifferent = nextDifferentEnd
        }
    }
    // finally, current will index the last element of the result slice
    return strings[:current+1]
}

And here a maybe more efficient one with comments, which copies in chunks with copy A lot of code for a simple task. I don't know if it is really more performant as simpler solutions (regarding code) and I am sure that it can be done easier.

func RemoveAdjacentDuplicates(strings []string) []string {
     // at least two elements need to be in the slice to have adjacent duplicates
     if len(strings) < 2 {
        return strings
    }
    current, nextDifferent, nextDifferentEnd := 0, 1, 0
    for nextDifferentEnd+1 < len(strings) {
        // search for next different element
        for nextDifferent < len(strings) && strings[current] == strings[nextDifferent] {
            nextDifferent++
        }
        // look for the largest subslice from the next different up to the next duplicate
        nextDifferentEnd = nextDifferent + 1
        for nextDifferentEnd < len(strings) && strings[nextDifferentEnd-1] != strings[nextDifferentEnd] {
            nextDifferentEnd++
        }
        // if we did not reach the and of the slice,
        // replace the duplicate(s) with the next subslice with different elements
        if nextDifferent < len(strings) {
            if current+1 != nextDifferent {
                copy(strings[current+1:], strings[nextDifferent:nextDifferentEnd])
            }
            current += nextDifferentEnd - nextDifferent
            nextDifferent = nextDifferentEnd
        }
    }
    // finally, current will index the last element of the result slice
    return strings[:current+1]
}
Small fix: the assignment has only to be done if current+1 != nextDifferent
Source Link

I am also new to Go, and I guess, we have the same Book :) I did it like this:

func RemoveAdjacentDuplicates(strings []string) []string {
    if len(strings) < 2 {
        return strings
    }
    current, nextDifferent := 0, 1
    for nextDifferent < len(strings) {
        for nextDifferent < len(strings) && strings[current] == strings[nextDifferent] {
            nextDifferent++
        }
        if nextDifferent < len(strings) {
            if current+1 != nextDifferent {
                strings[current+1] = strings[nextDifferent]
            }
            strings[current+1] = strings[nextDifferent]
            current++
        }
    }
    return strings[:current+1]
}

The advantage is, that you will not copy the whole tail of the slice several times when there are several ranges of duplicates. I am aware, that this also is not the best solution. One could copy whole ranges of unique strings at once instead of copy them one by one, which may be even more efficient.

I am also new to Go, and I guess, we have the same Book :) I did it like this:

func RemoveAdjacentDuplicates(strings []string) []string {
    if len(strings) < 2 {
        return strings
    }
    current, nextDifferent := 0, 1
    for nextDifferent < len(strings) {
        for nextDifferent < len(strings) && strings[current] == strings[nextDifferent] {
            nextDifferent++
        }
        if nextDifferent < len(strings) {
            strings[current+1] = strings[nextDifferent]
            current++
        }
    }
    return strings[:current+1]
}

The advantage is, that you will not copy the whole tail of the slice several times when there are several ranges of duplicates. I am aware, that this also is not the best solution. One could copy whole ranges of unique strings at once instead of copy them one by one, which may be even more efficient.

I am also new to Go, and I guess, we have the same Book :) I did it like this:

func RemoveAdjacentDuplicates(strings []string) []string {
    if len(strings) < 2 {
        return strings
    }
    current, nextDifferent := 0, 1
    for nextDifferent < len(strings) {
        for nextDifferent < len(strings) && strings[current] == strings[nextDifferent] {
            nextDifferent++
        }
        if nextDifferent < len(strings) {
            if current+1 != nextDifferent {
                strings[current+1] = strings[nextDifferent]
            }
            strings[current+1] = strings[nextDifferent]
            current++
        }
    }
    return strings[:current+1]
}

The advantage is, that you will not copy the whole tail of the slice several times when there are several ranges of duplicates. I am aware, that this also is not the best solution. One could copy whole ranges of unique strings at once instead of copy them one by one, which may be even more efficient.

Source Link
Loading