ルーンとは?


188

rune囲碁とは何ですか?

私はグーグルしてきましたが、Golangは1行でのみ言っています:はのruneエイリアスですint32

しかし、整数がスワッピングケースのように使用されるのはなぜですか?

以下は、関数swapcaseです。すべての何である<=とは-

そして、なぜswitch引数がないのですか?

&&意味すべきであるしかし何ですかr <= 'z'

func SwapRune(r rune) rune {
    switch {
    case 'a' <= r && r <= 'z':
        return r - 'a' + 'A'
    case 'A' <= r && r <= 'Z':
        return r - 'A' + 'a'
    default:
        return r
    }
}

それらのほとんどはhttp://play.golang.org/p/H6wjLZj6lWからのものです

func SwapCase(str string) string {
    return strings.Map(SwapRune, str)
}

これは、スワップされた文字列を返すことができるようにマッピングさrunestringていることを理解しています。しかし、私は正確にどのように理解していないruneか、byteここに動作します。


追記:これは、若い読者はそれがために何をしたいかもしれない何をしない英単語「カフェ」他者 -おろか他の言語を。Goには、この種の変換の実際に役立つバリアントを適切にサポートするライブラリがあります。
RedGrittyBrick 2018

2
「rune」という単語がどこから来たのか知りたい場合:en.wikipedia.org/wiki/Runic_(Unicode_block)
Matt Browne

[]rune、ブール型、数値型、または文字列型に設定できます。stackoverflow.com/a/62739051/12817546を参照してください。
トムJ

回答:


149

ルーンリテラルは32ビット整数値ですただし、型指定されていない定数なので、型が変わる可能性があります)。それらはUnicodeコードポイントを表します。たとえば、ルーンリテラル'a'は実際には数値97です。

したがって、プログラムは次のコードとほとんど同じです。

package main

import "fmt"

func SwapRune(r rune) rune {
    switch {
    case 97 <= r && r <= 122:
        return r - 32
    case 65 <= r && r <= 90:
        return r + 32
    default:
        return r
    }
}

func main() {
    fmt.Println(SwapRune('a'))
}

あなたがその範囲のASCIIと同一であるUnicodeマッピングを見たとしたら、それは明白であるべきです。さらに、32は実際には、文字の大文字と小文字のコードポイント間のオフセットです。したがって、に追加32する'A'ことで取得し'a'、その逆も同様です。


12
これは明らかに、ASCII文字のみで機能し、「ä」などの付加された文字では機能しません。「ı」(U + 0131)などのより複雑なケースはもちろんです。Goには、などの小文字にマップする特別な機能がありますunicode.ToLower(r rune) rune
2013年

2
そして、すべてのコードポイントのための作品だけではなく、AZことSwapCase機能付き@ topskipの正しい答えに追加するには:func SwapRune(r rune) rune { if unicode.IsUpper(r) { r = unicode.ToLower(r) } else { r = unicode.ToUpper(r) }; return r }
ANisus

22
ルーンはint32値です。それが全体の答えです。「マッピング」されていません。
thwd 2013年

@AlixAxel:SimpleFoldの動作は基本的に同じです(ほとんどのルーンにToLowerとToUpperも使用されます)。differs->Dz、Dz->dz、dz->DZなど、場合によっては異なります。私のSwapRuneは代わりにDZ->dz、Dz->DZ、dz->DZを実行します。私はあなたの提案をより気に入っています:)
ANisus

3
それで、ルーン文字はC文字に似ていますか?
ケニー・ワーデン2017

53

Go langリリースノートから:http : //golang.org/doc/go1#rune

ルーンはタイプです。これは32ビットを占有し、Unicode CodePointを表すことを目的としています。類推として、「ASCII」でエンコードされた英語の文字セットには128のコードポイントがあります。したがって、バイト(8ビット)内に収まることができます。この(誤った)仮定から、Cは文字を「バイト」charとして、「文字列」を「文字のシーケンス」として扱いましたchar*

しかし、何を推測します。「abcde ..」記号以外にも、人間が発明した記号は他にもたくさんあります。そして、非常に多くあり、それらをエンコードするために32ビットが必要です。

golangでは、aはのstringシーケンスですbytes。ただし、複数のバイトでルーンコードポイントを表すことができるため、文字列値にルーンを含めることもできます。したがって、に変換したり[]rune、その逆を行うことができます。

ユニコードパッケージhttp://golang.org/pkg/unicode/は、チャレンジの豊かさを味わうことができます。


6
最近のUnicode 6.3では、110,000を超える記号が定義されています。これは、各コードポイントの少なくとも21ビット表現を必要とするruneようなものであるint32とビットがたくさんあります。
Rick-777

2
あなたは「a stringrunesのシーケンスです」と言います-それは本当ではないと思いますか?Goブログ:「文字列はバイトの集まりです」; Go lang仕様:「文字列値は(おそらく空の)バイトシーケンスです」
Chris Martin

1
まだ混乱していますが、文字列はルーン文字の配列ですか、それともバイトの配列ですか?それらは交換可能ですか?
gogofan 2017

1
@prvnそれは間違っています。それは、画像がバイトのシーケンスではなく、ピクセルのシーケンスであると言っているようなものです。しかし、実際には、その下には一連のバイトがあります。文字列はルーン文字ではなく、一連のバイトです。仕様をお読みください。
イナンクムス

1
@prvnしかし、あなたは言うことができませんnot bytes。次に、「文字列はルーン文字で構成され、ルーン文字はバイトで構成されます」のようなものです。また。それは完全に真実ではありません。
Inanc Gumus 2018

28

素人が理解できるように、私は自分の言語をシンプルに保つようにしましたrune

ルーンはキャラクターです。それでおしまい。

1文字です。それは、世界中のあらゆる場所のあらゆる言語のあらゆるアルファベットのキャラクターです。

使用する文字列を取得するには

double-quotes ""

または

back-ticks ``

文字列はルーンとは異なります。ルーンで使用します

single-quotes ''

ルーンはint32...の別名でもあります。

runeがのエイリアスでint32ある理由は、以下のようなコーディングスキームで ここに画像の説明を入力してください

各文字はいくつかの番号にマップされるので、それが格納されている番号です。たとえば、にマップ97と、我々はその数を保存するとき、それはただの数ですので、の道のルーンがint32型の別名であること。しかし、ただの数ではありません。これは、32の「0と1」または「4」バイトの数値です。(注:UTF-8は4バイトのコード化スキームです)

ルーン文字と文字列の関係は?

文字列はルーン文字のコレクションです。次のコードでは:

    package main

    import (
        "fmt"
    )

    func main() {
        fmt.Println([]byte("Hello"))
    }

文字列をバイトのストリームに変換しようとします。出力は次のとおりです。

[72 101 108 108 111]

その文字列を構成する各バイトはルーン文字であることがわかります。


2
A string is not a collection of runesこれは厳密には正しくありません。代わりに、文字列はutf8でエンコードされたバイトスライスです。文字列内の各文字は実際には1〜3バイト、各ルーンは4バイトを使用します。文字列と[] runeの間で変換できますが、それらは異なります。
Eric Wang

2
ルーンは文字ではありません。ルーンはUnicodeコードポイントを表します。また、コードポイントは必ずしも1文字を指す必要はありません。
Inanc Gumus、

「ルーンはint32のエイリアスでもある」と追加する価値はありますが、それは貧弱な人の圧縮に役立つことを意味するわけではありません... 55296のようなものにヒットした場合、文字列変換は誤ったものになります:Go Playground
kubanczyk

27

fabrizioMの回答にコメントを投稿するのに十分な評判がないため、代わりにここに投稿する必要があります。

ファブリツィオの答えはほぼ正しいです、そして彼は確かに問題の本質を捕らえました-作られなければならない区別がありますが。

文字列は必ずしもルーン文字のシーケンスではありません。それはバイトのスライス'、オーバーラッパーですスライスゴー配列のラッパーであること。これはどのような違いがありますか?

ルーンタイプは、必ずしもビット×* 32のいくつかの数を有することになるルーンタイプの値のシーケンスを意味する、必ずしも32ビット値です。文字列はバイトのシーケンスであり、代わりにx * 8ビットの長さを持ちます。すべての文字列が実際にUnicodeであった場合、この違いによる影響はありません。ただし、文字列はバイトのスライスであるため、GoはASCIIまたはその他の任意のバイトエンコーディングを使用できます。

ただし、文字列リテラルは、UTF-8でエンコードされたソースに書き込む必要があります。

情報源:http : //blog.golang.org/strings


1
いい視点ね !各ルーンには4バイトが必要ですが、string内の各文字はutf8でエンコードされているため、最大で1〜3バイトのみです。
Eric Wang

16

(上記の答えはまだ違い&関係間の状態なかったことを手に入れた気持ちstring[]rune、私は一例で別の答えを追加しようとするので、非常に明確にします。)

通り@Strangeworkの答えが言った、string[]rune静かに異なっています。

違い- string[]rune

  • string value読み取り専用のバイトスライスです。また、文字列リテラルはutf-8でエンコードされます。の各文字はstring実際には1〜3バイトruneかかりますが、それぞれ4バイトかかります
  • の場合stringlen()とインデックスは両方ともバイトに基づいています。
  • の場合[]runelen()インデックスとインデックスの両方がルーン(またはint32)に基づいています。

関係- string[]rune

  • からstringに変換する[]runeと、その文字列の各utf-8文字はになりますrune
  • 同様に、逆変換では、からに変換する[]runestring、それぞれruneがutf-8文字になりstringます。

チップ:

  • stringとの間で変換できますが[]rune、タイプと全体のサイズは異なります。

(それをより明確に示すために例を追加します。)


コード

string_rune_compare.go:

// string & rune compare,
package main

import "fmt"

// string & rune compare,
func stringAndRuneCompare() {
    // string,
    s := "hello你好"

    fmt.Printf("%s, type: %T, len: %d\n", s, s, len(s))
    fmt.Printf("s[%d]: %v, type: %T\n", 0, s[0], s[0])
    li := len(s) - 1 // last index,
    fmt.Printf("s[%d]: %v, type: %T\n\n", li, s[li], s[li])

    // []rune
    rs := []rune(s)
    fmt.Printf("%v, type: %T, len: %d\n", rs, rs, len(rs))
}

func main() {
    stringAndRuneCompare()
}

実行:

string_rune_compare.goを実行します

出力:

hello你好, type: string, len: 11
s[0]: 104, type: uint8
s[10]: 189, type: uint8

[104 101 108 108 111 20320 22909], type: []int32, len: 7

説明:

  • 文字列のhello你好長さは11です。これは、最初の5文字はそれぞれ1バイトのみを使用し、最後の2文字はそれぞれ3バイトを使用するためです。

    • したがって、 total bytes = 5 * 1 + 2 * 3 = 11
    • 以来、len()文字列の最初の行が印刷され、従って、バイトに基づいていますlen: 11
    • 文字列のインデックスもバイトに基づいているため、次の2行はタイプの値を出力しますuint8(これbyteは、エイリアスタイプであるuint8ので)。
  • をに変換するstring[]rune、7つのutf8文字、つまり7つのルーン文字が見つかりました。

    • ためlen()[]rune最後の行が印刷され、従って、ルーンに基づいていますlen: 7
    • []runeインデックスを介して操作する場合、ルーンに基づいてアクセスします。
      各ルーンは元の文字列のutf8文字からのものであるため、両方ともlen()インデックス操作[]runeはutf8文字に基づいていると言えます。

「文字列の場合、len()とインデックスは両方ともバイトに基づいています。」それについてもう少し説明してもらえますか?実行するとfmt.Println("hello你好"[0])、バイトではなく実際のUTF-8コードポイントが返されます。
ジュリアン

@Julian答えでプログラムの出力を見てください。なぜならs[0]、それは印刷されs[0]: 104, type: uint8、型はでありuint8、そのバイトを意味します。hutf-8のようなASCII文字の場合も、1バイトを使用してそれを表すため、コードポイントは1バイトと同じです。のような漢字の場合、3バイトを使用します。
Eric Wang

明確化する例。ここであなたを引用しましたstackoverflow.com/a/62739051/12817546
トムJ

7

他の皆がルーン文字に関連する部分をカバーしたので、私はそれについて話をしません。

ただし、switch引数がないことに関連する問題もあります。これは、Golangではswitch、式なしでif / elseロジックを表現する代替方法であるためです。たとえば、次のように記述します。

t := time.Now()
switch {
case t.Hour() < 12:
    fmt.Println("It's before noon")
default:
    fmt.Println("It's after noon")
}

これを書くのと同じです:

t := time.Now()
if t.Hour() < 12 {
    fmt.Println("It's before noon")
} else {
    fmt.Println("It's after noon")
}

詳しくはこちらをご覧ください


0

ルーンはint32値であるため、Unicodeコードポイントを表すために使用されるGoタイプです。Unicodeコードポイントまたはコード位置は、単一のUnicode文字を表すために通常使用される数値です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.