Определить что все символы в строке уникальны

Стоит задача, определить, что все символы в строке уникальны. На входе например

test string

на выходе

test string - false

На входе

abcde

на выходе

abcde - true

Я делаю так

package main

import (
    "log"
    "strings"
)

func CountLetters(str string) (bool, string) {
    slcstr := strings.Split(str, "")
    mpbool := make(map[string]bool, 0)
    for _, item := range slcstr {
        _, ok := mpbool[item]
        if ok {
            return false, str
        }
        mpbool[item] = true
    }
    return true, str
}

func main() {
    log.Println(CountLetters("test"))
}

Но может есть какие то еще способы или есть какой-то классический способ? И еще меня немного смущает что медленная функция, думаю из-за пакета strings. Есть ли вариант без него и без приведения типов?


Ответы (1 шт):

Автор решения: aksioto

Можно обойтись только слайсами

package main

import "fmt"

func main() {
    fmt.Println(CountLetters("abcde"))
    fmt.Println(CountLetters("abcdee"))
}

func CountLetters(str string) (string, bool) {
    for i := 0; i < len(str); i++ {
        for j := i + 1; j < len(str); j++ {
            if str[i] == str[j] {
                return str, false
            }
        }
    }

    return str, true
}
abcde true
abcdee false

Вариант с юникодом

func CountLettersUnicode(str string) (string, bool) {
    chars := []rune(str)
    length := len(chars)
    for i := 0; i < length; i++ {
        for j := i + 1; j < length; j++ {
            if chars[j] == chars[i] {
                return str, false
            }
        }
    }
    return str, true
}

UPD: Сделал тест производительности. Первый вариант самый шустрый.

package benching

import (
    "strings"
    "testing"
)

func CountLetters1(str string) (string, bool) {
    for i := 0; i < len(str); i++ {
        for j := i + 1; j < len(str); j++ {
            if str[i] == str[j] {
                return str, false
            }
        }
    }

    return str, true
}

func CountLetters2(str string) (string, bool) {
    slcstr := strings.Split(str, "")
    mpbool := make(map[string]bool, 0)
    for _, item := range slcstr {
        _, ok := mpbool[item]
        if ok {
            return str, false
        }
        mpbool[item] = true
    }
    return str, true
}

func BenchmarkCountLetters(b *testing.B) {
    b.Run("1", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            CountLetters1("abcde")
        }
    })
    b.Run("2", func(b *testing.B) {
        for i := 0; i < b.N; i++ {
            CountLetters2("abcde")
        }
    })
}
go test -bench BenchmarkCountLetters -benchtime=10000000x -benchmem

goos: windows
goarch: amd64
pkg: benching
cpu: Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz
BenchmarkCountLetters/1-8       10000000                12.96 ns/op            0 B/op          0 allocs/op
BenchmarkCountLetters/2-8       10000000               331.0 ns/op            80 B/op          1 allocs/op
PASS
ok      benching        3.964s
→ Ссылка