8

Here is my code snippet:

var converter = map[rune]rune {//some data}

sample := "⌘こんにちは"

var tmp string

for _, runeValue := range sample {
        fmt.Printf("%+q", runeValue)
        tmp = fmt.Sprintf("%+q", runeValue)
    }

The output of fmt.Printf("%+q", runeValue) is:

'\u2318'
'\u3053'
'\u3093'
'\u306b'
'\u3061'
'\u306f'

These value are literally rune but as the return type of Sprintf is string, I cannot use it in my map which is [rune]rune. I was wondering how can I convert string to rune, or in other words how can I handle this problem?

icza
  • 389,944
  • 63
  • 907
  • 827
Amid
  • 442
  • 2
  • 8
  • 15
  • `[]rune(sample)` ? like in https://play.golang.org/p/ISPOEvSzFQW –  Dec 08 '20 at 09:04
  • 2
    A `string` is not a `rune`, it may contain multiple `rune`s. The `for range` iterates over its runes, or you may use a conversion like `[]rune(sample)` to get all runes of a `string` as a slice. What is your question exactly? – icza Dec 08 '20 at 09:07
  • thanks @mh-cbon. I don't want to just print them on the console, but I want to use the values in my map. – Amid Dec 08 '20 at 09:12
  • Thanks @icza, you know i want to map some rune values to another rune values. Thus by using `range` over a string, I want to take each `rune` and use it in my map to find the corresponding `rune`. btw, I am trying to implement a character encoding – Amid Dec 08 '20 at 09:14
  • @icze, but my problem is how to take that rune. By using Rob pike's advice in [here](https://blog.golang.org/strings), I used `"%+q"` to take each rune but `Sprintf` returns as a string. I was wondering if there is another way which I can use `"%+q"` and returns as a rune – Amid Dec 08 '20 at 09:20
  • https://blog.golang.org/strings – Volker Dec 08 '20 at 09:36
  • Thanks @Volker, But I have studied Rob Pike's advice as I mentioned in previous comment. – Amid Dec 08 '20 at 09:44

2 Answers2

9

A string is not a single rune, it may contain multiple runes. You may use a simple type conversion to convert a string to a []runes containing all its runes like []rune(sample).

The for range iterates over the runes of a string, so in your example runeValue is of type rune, you may use it in your converter map, e.g.:

var converter = map[rune]rune{}
sample := "⌘こんにちは"
for _, runeValue := range sample {
    converter[runeValue] = runeValue
}
fmt.Println(converter)

But since rune is an alias for int32, printing the above converter map will print integer numbers, output will be:

map[8984:8984 12371:12371 12385:12385 12395:12395 12399:12399 12435:12435]

If you want to print characters, use the %c verb of fmt.Printf():

fmt.Printf("%c\n", converter)

Which will output:

map[⌘:⌘ こ:こ ち:ち に:に は:は ん:ん]

Try the examples on the Go Playground.

If you want to replace (switch) certain runes in a string, use the strings.Map() function, for example:

sample := "⌘こんにちは"

result := strings.Map(func(r rune) rune {
    if r == '⌘' {
        return 'a'
    }
    if r == 'こ' {
        return 'b'
    }
    return r
}, sample)

fmt.Println(result)

Which outputs (try it on the Go Playground):

abんにちは

If you want the replacements defined by a converter map:

var converter = map[rune]rune{
    '⌘': 'a',
    'こ': 'b',
}
sample := "⌘こんにちは"

result := strings.Map(func(r rune) rune {
    if c, ok := converter[r]; ok {
        return c
    }
    return r
}, sample)

fmt.Println(result)

This outputs the same. Try this one on the Go Playground.

icza
  • 389,944
  • 63
  • 907
  • 827
6

Convert string to rune array:

runeArray := []rune("пример")

StasVo
  • 554
  • 6
  • 6