A String a Julia nyelvben karakterek rendezett sorozata. Ahogy a kézikönyv rámutat: „Persze az igazi baj akkor kezdődik, amikor valaki azt kérdezi, mi is az a karakter."
Ennek a bonyolultságnak a nagy részét részletesebben a Chars fogalom tárgyalja, de röviden:
Általában a stringeket idézőjelek közé zárjuk: " ".
Az egyszeres idézőjelet ' ' csak Chars esetén használjuk.
Három idézőjelet """ """ is használhatunk, így a stringen belül " is szerepelhet escape-elés nélkül.
Ennél is fontosabb, hogy a többsoros stringekről a felesleges behúzást eltávolítja.
julia> """
Multiline
String
"""
"Multiline\nString\n"
A C-től kezdődő nyelvek többségéhez hasonlóan a Julia is visszaperjelet \ használ az escape-eléshez:
\n beírására.\$ (lásd alább).A string egy bejárható gyűjtemény, ezért a for ... in ciklus anélkül működik, hogy karakterek vektorává kellene alakítani.
julia> s = "Julia"
"Julia"
# admittedly, this is a silly example
julia> for c in s; print(c, "; "); end
J; u; l; i; a;
Az ilyen iterálásnak az az előnye, hogy a Julia a nem ASCII stringek esetében is helyesen kezeli a karakterhatárokat. Mindennek a jelentősége a következő szakaszban válik világosabbá.
Elvileg a stringek pontosan úgy indexelhetők, mint a vektorok:
julia> s[1], s[5]
('J', 'a')
Ez nyilvánvalóan működik egy olyan ASCII string esetén, mint a „Julia", de figyelmen kívül hagyja a világ nyelveinek nagy részét.
Vegyük a Beowulf egyik karakterét, amelyet mintegy 15 évszázaddal ezelőtt óangolul írtak.
A „Hrōðgār" nyilvánvalóan 7 karakterből áll, de nem mindegyikük ASCII.
julia> king = "Hrōðgār"
"Hrōðgār"
julia> length(king)
7
julia> isascii(king)
false
# collect() converts to a Char vector:
julia> collect(king)
7-element Vector{Char}:
'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)
'r': ASCII/Unicode U+0072 (category Ll: Letter, lowercase)
'ō': Unicode U+014D (category Ll: Letter, lowercase)
'ð': Unicode U+00F0 (category Ll: Letter, lowercase)
'g': ASCII/Unicode U+0067 (category Ll: Letter, lowercase)
'ā': Unicode U+0101 (category Ll: Letter, lowercase)
'r': ASCII/Unicode U+0072 (category Ll: Letter, lowercase)
Egy ilyen string indexelése jól indul, de egy ponton elakad:
julia> king[3]
'ō': Unicode U+014D (category Ll: Letter, lowercase)
julia> king[4]
ERROR: StringIndexError: invalid index [4], valid nearby indices [3]=>'ō', [5]=>'ð'
A probléma az, hogy az ilyen indexelés bájtokat számol, amelyek a nem ASCII stringek esetében nincsenek 1:1 kapcsolatban a karakterekkel.
Egy Unicode/UTF-8 karakter akár 4 bájtot is igénybe vehet, és a Chars fogalom ezt részletesebben is kifejti.
Sok nyelv a + operátort használja stringek összefűzésére, de a Julia nem.
Legalább a hibaüzenet segítőkész.
julia> "s1 " + "s2"
ERROR: MethodError: no method matching +(::String, ::String)
The function `+` exists, but no method is defined for this combination of argument types.
String concatenation is performed with *
julia> "s1 " * "s2"
"s1 s2"
A string() függvény tetszőleges számú stringet fűz össze.
julia> string("lots ", "of ", "bits")
"lots of bits"
A join() függvény ugyanezt teszi, és stringek vektorát is összefűzi egy megadott elválasztóval (amely alapértelmezésben "").
julia> join(["lots", "of", "bits"], "_")
"lots_of_bits"
Vegyük észre, hogy a stringek megváltoztathatatlanok, és az összefűzés másolással jár. Ezért a cikluson belüli ismételt összefűzés nem hatékony, jobb, ha a darabokat egy vektorban gyűjtjük össze, és a végén fűzzük össze az egészet.
Egyszerű:
julia> repeat("Abc", 5)
"AbcAbcAbcAbcAbc"
Sok nyelvben van mód arra, hogy kiszámított értékeket illesszünk stringekbe, bár abban meglepően nagy az egyet nem értés, hogy melyik a legjobb szintaxis.
A Juliában az interpolált értékeket $ előzi meg.
julia> myvar = 42
42
julia> "myvar evaluates to $myvar"
"myvar evaluates to 42"
julia> r = 5.3
5.3
julia> "A circle of radius $r has area $(π * r^2)"
"A circle of radius 5.3 has area 88.24733763933729"
A zárójelek kötelezőek, ha elhagyásuk kétértelmű lenne, de egyetlen, szóközzel követett azonosító esetén elhagyhatók.
Ha a stringben $ szerepel, escape-eld \$ formában.
Jegyezzük meg a korlátot: az interpoláció jelenleg nem tesz lehetővé formázást, például a megjelenítendő tizedesjegyek számát.
Megoldások:
round() függvénybe.@sprintf() makrót alább ismertetjük.@sprintf()A stringek összeállítása feletti finomabb vezérléshez a Julia a C-ből (és számos későbbi nyelvből: a Wikipédia mintegy 30-at sorol fel) másolja a sprintf függvényt.
A Juliában ezt a Printf modulon belüli macro valósítja meg, innen a @ előtag.
julia> using Printf
julia> r = 5.3
5.3
julia> @sprintf("A circle of radius %.1f has area %.2f", r, π * r^2)
"A circle of radius 5.3 has area 88.25"
Az egyszerűség kedvéért ez a szakasz azokra a függvényekre összpontosít, amelyek új stringet adnak vissza, és a bemenetet változatlanul hagyják.
Soknak van egy ! utótaggal jelölt megfelelője, amely helyben módosítja a bemenetet.
Milyen hosszú egy string? Néha attól függ, hogyan számolsz.
Az egyszerű eset az ASCII string, ahol minden karakter 1 bájtot foglal el.
julia> string_asc = "Julia"
"Julia"
julia> length(string_asc)
5
julia> sizeof(string_asc)
5
A length() függvény a karakterek számát adja vissza, a sizeof() pedig a bájtokét.
Ez a különbség más karakterkészleteknél válik fontossá:
julia> king = "Hrōðgār"
"Hrōðgār"
julia> length(king)
7
julia> sizeof(king)
10
A programozásban gyakori művelet egy hosszú stringet darabokra bontani egy vagy több karakterből álló elválasztó string alapján.
A legáltalánosabb esetben a split() függvényt használjuk.
Az elválasztó alapértelmezésben bármilyen whitespace, de más is megadható.
julia> split("my little string")
3-element Vector{SubString{String}}:
"my"
"little"
"string"
julia> split("My_snake_case_string", "_")
4-element Vector{SubString{String}}:
"My"
"snake"
"case"
"string"
Ezek a példák egy stringet kisebb stringekre bontanak. Egy string karakterekre bontása más művelet.
julia> collect("input string")
12-element Vector{Char}:
'i': ASCII/Unicode U+0069 (category Ll: Letter, lowercase)
'n': ASCII/Unicode U+006E (category Ll: Letter, lowercase)
'p': ASCII/Unicode U+0070 (category Ll: Letter, lowercase)
'u': ASCII/Unicode U+0075 (category Ll: Letter, lowercase)
't': ASCII/Unicode U+0074 (category Ll: Letter, lowercase)
' ': ASCII/Unicode U+0020 (category Zs: Separator, space)
's': ASCII/Unicode U+0073 (category Ll: Letter, lowercase)
't': ASCII/Unicode U+0074 (category Ll: Letter, lowercase)
'r': ASCII/Unicode U+0072 (category Ll: Letter, lowercase)
'i': ASCII/Unicode U+0069 (category Ll: Letter, lowercase)
'n': ASCII/Unicode U+006E (category Ll: Letter, lowercase)
'g': ASCII/Unicode U+0067 (category Ll: Letter, lowercase)
Tartalmaz-e egy string egy megadott részstringet?
Furcsamód két függvény is teszteli ezt: az occursin() és a contains() csak az argumentumaik sorrendjében térnek el.
julia> needle = "Julia"
"Julia"
julia> haystack = "Python, Julia and R"
"Python, Julia and R"
julia> occursin(needle, haystack)
true
julia> contains(haystack, needle)
true
A pozíció pontosabb meghatározásához:
julia> startswith(haystack, "Python")
true
julia> endswith(haystack, "Python")
false
Egy részstring kezdő:záró indexeinek megkereséséhez több függvényünk is van:
julia> findfirst(needle, haystack)
9:13
Részstringek cseréjéhez sorold fel a változtatásokat x => y szintaxissal.
julia> replace("abc", "a"=>"b", "b"=>"c", "c"=>"a")
"bca"
A Julia 1.7 óta a replace függvény tetszőleges számú változtatást fogadhat, azzal a garanciával, hogy a csere során egyetlen karakter sem változik meg egynél többször.
Az x => y szintaxist pair-nek nevezzük; ez egy fontos típus a Juliában, amelyről részletesebben a Dicts and Pairs fogalom szól.
Megjegyzés: Az egyszerűség kedvéért a fenti példák mind string literálokat használnak. A függvények közül sok általánosabb, és reguláris kifejezésekkel is működik. Erre egy későbbi fogalomban térünk vissza.
Gyakran kell egy string elejéről és/vagy végéről whitespace-t eltávolítanunk.
Erre valók az lstrip() (bal), rstrip() (jobb) és strip() (mindkettő) függvények.
julia> strip("\n\t useful_bit\n\n")
"useful_bit"
Ezeknek a függvényeknek meglehetősen beszédes a nevük:
julia> s = repeat("aBcD ", 5)
"aBcD aBcD aBcD aBcD aBcD "
julia> uppercase(s)
"ABCD ABCD ABCD ABCD ABCD "
julia> lowercase(s)
"abcd abcd abcd abcd abcd "
julia> titlecase(s) # Initial letter of each word uppercase
"Abcd Abcd Abcd Abcd Abcd "
Gyakran hasznos a számok és stringreprezentációjuk közötti átalakítás.
A számból stringgé alakítás egyszerű, bár az alapértelmezett 10-től eltérő számrendszerhez egy plusz paraméter kell:
julia> string(42)
"42"
julia> string(42, base=16)
"2a"
julia> string(42, base=2)
"101010"
Egy string parszolása számérték előállításához kicsit bonyolultabb, és több hibalehetőséget rejt magában. A cél numerikus típus megadása kötelező. A számrendszer megadása opcionális, alapértelmezésben 10.
julia> parse(Int, "42")
42
julia> parse(Float64, "42")
42.0
julia> parse(Int, "42?")
ERROR: ArgumentError: invalid base 10 digit '?' in "42?"
julia> parse(Int, "42 ") # whitespace may be tolerated
42
Néha hasznos, ha elnyomjuk a szokásos interpolációt és escape-elést a stringeken belül.
Ehhez írd a nyitó idézőjel elé a raw szót.
julia> x = 10
10
julia> "x = $x if we use \$ for interpolation"
"x = 10 if we use \$ for interpolation"
julia> raw"x = $x if we use \$ for interpolation"
"x = \$x if we use \\\$ for interpolation"
A reguláris kifejezéseknek saját bonyolult szintaxisuk van, és a Julia két hasznos stringtípust kínál: a r" " a regexhez és az s" " a rögzített részekkel való munkához.
Számos más különleges string ritkábban fordul elő az Exercism-stílusú programozásban, bár könyvtárak készítésekor széles körben használják.
v"x.y.z" a szoftverkiadások főverzió.alverzió.javítás számozását kezelik.b" " megkerülik a Unicode karakterhatárokat, és bájt szinten működnek.