Rune nedir?


189

Nedir runeGo'da ?

Ben googling yapıyorum ama Golang sadece bir satırda söylüyor: runeiçin bir takma adint32 .

Ama nasıl geliyor tamsayı takas durumlarda gibi kullanılır?

Aşağıda bir işlev swapcase bulunmaktadır. Bütün bunlar ne <=ve -?

Ve neden switchhiç argüman yok?

&&demek gerekir ve ancak ne 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
    }
}

Çoğu http://play.golang.org/p/H6wjLZj6lW adresinden

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

Bu eşleme anlamak runeiçin stringonu takas dize geri dönebilmek için. Ama tam olarak nasıl çalıştığını runeveya byteburada nasıl çalıştığını anlamıyorum .


Sidenote: Bu, genç okuyucular İngilizce "kafe" ve diğerleri için diğer dilleri bırakmasını istediklerini yapmaz . Go, bu tür bir dönüşümün gerçekten yararlı varyantları için iyi bir desteğe sahip kütüphanelere sahiptir.
RedGrittyBrick

2
Herkes "rune" kelimesinin nereden geldiğini bilmek isterse: en.wikipedia.org/wiki/Runic_(Unicode_block)
Matt Browne

A []rune, bir boole, sayısal veya dize türüne ayarlanabilir. Bkz. Stackoverflow.com/a/62739051/12817546 .
Tom J

Yanıtlar:


149

Rune değişmez değerleri yalnızca 32 bit tamsayı değerleridir ( ancak türsüz sabitlerdir, bu nedenle türleri değişebilir ). Unicode kod noktalarını temsil ederler. Örneğin, rune değişmez 'a'değeri aslında sayıdır97 .

Bu nedenle programınız hemen hemen aşağıdakilere eşdeğerdir:

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

Bu aralıktaki ASCII ile aynı olan Unicode eşlemesine bakacak olsaydınız açık olmalıdır . Ayrıca, 32 aslında karakterin büyük ve küçük harf kod noktaları arasındaki ofsettir. Yani ekleyerek 32için 'A'elde edersiniz 'a'tersi ve yardımcısı.


12
Bu açıkça sadece ASCII karakterleri için geçerlidir ve '' (U + 0131) gibi daha karmaşık vakaların yanı sıra 'ä' gibi suçlanan karakterler için geçerli değildir. Go, küçük harflerle eşleştirmek için özel işlevlere sahiptir unicode.ToLower(r rune) rune.
6'da atlayın

2
Ve sadece az değil tüm kod noktaları için çalışan bir SwapCase fonksiyonu ile @ topskip'in doğru cevabına eklemek için:func SwapRune(r rune) rune { if unicode.IsUpper(r) { r = unicode.ToLower(r) } else { r = unicode.ToUpper(r) }; return r }
ANisus

22
Runes int32 değerleridir. Bütün cevap bu. Onlar "haritalanmıyor" .
thwd

@AlixAxel: SimpleFold'un davranışı aslında aynıdır (çoğu run için ToLower ve ToUpper da kullanır). Farklı olduğu bazı durumlar vardır: DZ-> Dz, Dz-> dz, dz-> DZ. Benim SwapRune yerine gitmek istiyorum: DZ-> dz, Dz-> DZ, dz-> DZ. Önerinizi daha iyi
beğeniyorum

3
Peki runeler C karakterlerine benzer mi?
Kenny Worden

53

Go lang sürüm notlarından: http://golang.org/doc/go1#rune

Rune bir Tür. 32bit'i kaplar ve bir Unicode CodePoint'i temsil eder . Bir benzetme olarak, 'ASCII'de kodlanan ingilizce karakter kümesinin 128 kod noktası vardır. Böylece bir bayt (8bit) içine sığabilir. Bu (hatalı) varsayımdan C karakterleri 'bayt' charve 'dizeleri' 'karakter dizisi' olarak ele aldı char*.

Ama tahmin et ne oldu. İnsanlar tarafından 'abcde ..' sembolleri dışında icat edilen birçok sembol daha vardır. Ve onları kodlamak için 32 bit'e ihtiyacımız var.

Golang'da a stringbir dizisidir bytes. Bununla birlikte, birden çok bayt bir rune kod noktasını temsil edebildiğinden, bir dize değeri de runes içerebilir. Böylece, a []runeveya tersine dönüştürülebilir .

Unicode paketi http://golang.org/pkg/unicode/ , meydan okuma zenginliğinin tadına bakabilir.


6
Son Unicode 6.3 ile 110.000'den fazla sembol tanımlanmıştır. Bu, her kod noktasının en az 21 bitlik gösterimini gerektirir, bu nedenle a rune, benzer int32ve bol miktarda bit içerir.
Rick-777

2
"A bir s stringdizisidir rune" dersiniz - bunun doğru olduğunu düşünmüyorum? Blog'a gidin : "bir dize sadece bir bayt bayttır"; Git lang spec : "Bir dize değeri (muhtemelen boş) bayt dizisidir"
Chris Martin

1
Hala kafam karıştı, bu yüzden dize bir dizi runes veya bir bayt dizisi mi? Değiştirilebilir mi?
gogofan

1
@prvn Bu yanlış. Bir görüntünün bayt sırası değil, piksel sırası olduğunu söylemek gibidir. Ama aslında, altında bir dizi bayt var. Dize, bir bayt dizisidir, runik değil. Lütfen teknik özellikleri okuyun .
İnanç Gümüş

1
@prvn Ama söyleyemezsin not bytes. Sonra şöyle diyebilirsiniz: "Dizeler baytlardan oluşan runik ve runiklerden oluşur" Böyle bir şey. Sonra tekrardan. tamamen doğru değil.
İnanç Gumus

28

Bir meslekten olmayanların anlaması için dilimi basit tutmaya çalıştım rune.

Bir rune bir karakterdir. Bu kadar.

Tek bir karakter. Dünyanın herhangi bir yerinden herhangi bir dilden herhangi bir alfabeden bir karakter.

Bir dize almak için kullanırız

double-quotes ""

VEYA

back-ticks ``

Dize bir runeden farklıdır. Rünlerde kullanıyoruz

single-quotes ''

Şimdi bir rune de bir takma ad int32... Uh Ne?

Runenin bir takma ad olmasının nedeni int32, aşağıdaki gibi kodlama şemaları ile resim açıklamasını buraya girin

her karakter bir sayı ile eşleşir ve bu yüzden sakladığımız sayıdır. Örneğin, 97'ye bir harita ve bu sayıyı sakladığımızda bu sadece sayıdır ve bu nedenle rune int32 için bir takma addır. Ama sadece herhangi bir sayı değil. 32 'sıfır ve bir' veya '4' bayt içeren bir sayıdır. (Not: UTF-8, 4 baytlık bir kodlama şemasıdır)

Runes dizelerle nasıl ilişkilidir?

Dize, runelerin bir koleksiyonudur. Aşağıdaki kodda:

    package main

    import (
        "fmt"
    )

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

Bir dizeyi bayt akışına dönüştürmeye çalışırız. Çıktı:

[72 101 108 108 111]

Bu dizeyi oluşturan her baytın bir rune olduğunu görebiliriz.


2
A string is not a collection of runesbu kesinlikle doğru değil. Bunun yerine, dize utf8 ile kodlanmış bir bayt dilimidir. Dize içindeki her karakter aslında 1 ~ 3 bayt alırken, her rune 4 bayt alır. String ve [] rune arasında dönüştürebilirsiniz, ancak bunlar farklıdır.
Eric Wang

2
Rune bir karakter değil, rune unicode kod noktasını temsil eder. Ve bir kod noktası mutlaka bir karakteri göstermez.
İnanç Gümüş

Buna ek olarak değer "rune de int32 için bir takma addır" evet, ama bu kötü adam sıkıştırma için yararlı olduğu anlamına gelmez ... 55296 gibi bir şeye çarparsanız, dize dönüşümü
sapar

27

FabrizioM'un cevabına bir yorum göndermek için yeterli üne sahip değilim, bunun yerine burada yayınlamam gerekecek.

Fabrizio'nun cevabı büyük ölçüde doğrudur ve kesinlikle sorunun özünü yakalamıştır - ancak yapılması gereken bir ayrım vardır.

Bir dize mutlaka bir runik dizisi DEĞİLDİR . Bir 'dilim bayt', bir dilim üzerine bir sargıdır üzerinde bir sargıdır bir Go dizisi üzerinde bir sargıdır. Bu ne fark eder?

Bir rune türü zorunlu olarak 32 bitlik bir değerdir, yani rune türlerinin bir değerler dizisi mutlaka bir miktar bit x * 32'ye sahip olacaktır. Bayt dizisi olan dizelerin uzunluğu x * 8 bittir. Tüm dizeler aslında Unicode'da olsaydı, bu farkın hiçbir etkisi olmazdı. Dizeler bayt dilimleri olduğundanBununla birlikte, Go, ASCII veya başka bir rastgele bayt kodlaması kullanabilir.

Bununla birlikte, dize değişmezlerinin UTF-8'de kodlanan kaynağa yazılması gerekir.

Bilgi kaynağı: http://blog.golang.org/strings


1
İyi bir nokta ! Her rune 4 bayt gerektirir, ancak dizedeki her karakter utf8 ile kodlanır, bu nedenle en fazla 1 ~ 3 bayt olur.
Eric Wang

16

(Cevaplar yukarıdaki hala arasındaki farklılıkları ve ilişkileri ifade etmediği bir duygu var stringve []runeben örnekle başka bir yanıt eklemeyi deneyin diye, çok net.)

As @Strangeworkbireyin cevabı söyledi stringve []runesessiz farklıdır.

Farklar - string& []rune:

  • string valuesalt okunur bir bayt dilimidir. Ve, bir dize hazır bilgisi utf-8'de kodlanır. Her karakter stringaslında 1 ~ 3 bayt alırken, her karakter 4rune alır bayt
  • İçin string, hemlen() ve dizin baytlara dayalıdır.
  • Çünkü []rune, hem len()ve dizin rune (veya int32) tabanlıdır.

İlişkiler - string& []rune:

  • Eğer gelen dönüştürdüğünüzde stringiçin []runeo tellerden her utf-8 karakter bir hale gelirrune .
  • Dönüştüğünde Benzer şekilde, ters dönüşüm, []runeiçin string, her biri runebir UTF-8 karakter olur string.

İpuçları:

  • Sen arasında dönüştürebilir stringve []rune, ama yine de tip ve genel boyutta hem de farklıdır.

(Bunu daha net göstermek için bir örnek eklerim.)


kod

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

Yürütme:

git run string_rune_compare.go

Çıktı:

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

Açıklama:

  • Dizenin hello你好uzunluğu 11'dir, çünkü ilk 5 karakter her biri yalnızca 1 bayt alırken, son 2 Çince karakter her biri 3 bayt alır.

    • Böylece, total bytes = 5 * 1 + 2 * 3 = 11
    • Yana len()dizesini bayt dayanır, böylece ilk satır baskılılen: 11
    • Dize üzerindeki dizin de baytlara dayandığından, aşağıdaki 2 satır tür değerlerini yazdırır uint8(çünkü bytebir diğer ad türü uint8, halindeyken).
  • Dönüştürdüğünüzde stringiçin []rune, bu nedenle 7 utf8 karakter, 7 rünlerini bulundu.

    • Yana len()ile []runeRün dayanır, böylece son satır baskılı len: 7.
    • Eğer []runeindeks ile çalıştırırsanız , rune üzerindeki üsse erişir.
      Her rune orijinal dizgideki bir utf8 karakterinden olduğundan, hem len()indeks işleminin hem []runeutf8 karakterlerine dayandığını söyleyebilirsiniz .

"Dize için, hem len () hem de index baytlara dayanır." Bunu biraz daha açıklayabilir misiniz? Ne zaman fmt.Println("hello你好"[0])bayt yerine gerçek UTF-8 kod noktasını döndürür.
Julian

@Julian Lütfen cevaptaki programın çıktısına bir göz atın, s[0]yazdırın s[0]: 104, type: uint8, tür, uint8bir bayt anlamına gelir. hUtf-8 gibi ASCII karakterleri için bunu temsil etmek üzere tek bir bayt kullanılır, böylece kod noktası tek bayt ile aynıdır; ama gibi çin chars için , 3 bayt kullanır.
Eric Wang

Açıklayıcı örnek. Sizi burada alıntıladım stackoverflow.com/a/62739051/12817546 .
Tom J

7

Diğer herkes rünlerle ilgili kısmı ele aldı, bu yüzden bundan bahsetmeyeceğim.

Bununla birlikte, switchherhangi bir tartışmanın olmamasıyla ilgili bir soru da vardır . Bunun nedeni, Golang'da switchifade olmadan if / else mantığını ifade etmenin alternatif bir yoludur. Örneğin, şunu yazmak:

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

bunu yazmakla aynı:

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

Daha fazlasını buradan okuyabilirsiniz .


0

Bir rune bir int32 değeridir ve bu nedenle bir Unicode kod noktasını temsil etmek için kullanılan bir Go tipidir. Unicode kod noktası veya kod konumu, genellikle tek Unicode karakterleri temsil etmek için kullanılan sayısal bir değerdir;

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.