Treci la conținutul principal

Transformarea unei colecții

O transformare ia o colecție, de exemplu un slice sau un map, și construiește din ea o colecție nouă. Colecția originală nu este modificată.

În multe limbaje, listele și map-urile vin cu metode gata făcute, precum map, zip, associate și flatten. Go nu are aceste metode încorporate. În schimb, scrii o buclă for scurtă sau o mică funcție helper pe care o poți refolosi. Acesta este stilul Go și este scurt, odată ce știi tiparul.

Go are generice începând cu versiunea 1.18. O funcție generică lucrează cu orice tip de element. Lecțiile de pe această pagină folosesc generice (Go 1.21 sau mai nou), astfel încât un singur helper merge la fel de bine pentru numere, string-uri și struct-uri. Pachetele standard slices, maps și strings ajută și ele la sarcinile obișnuite.

Sintaxa unui helper Map generic

Aceasta este forma unui helper Map refolosibil. T este tipul elementelor de intrare, iar R este tipul elementelor din rezultat. Funcția f este apelată o dată pentru fiecare element, iar fiecare răspuns este adăugat în noul slice.

main.go
func Map[T, R any](items []T, f func(T) R) []R {
  result := make([]R, 0, len(items))
  for _, v := range items {
    result = append(result, f(v))
  }
  return result
}

Map

Operația map aplică aceeași funcție fiecărui element și adună răspunsurile într-un slice nou, de aceeași lungime. De exemplu, poate transforma [1 2 3] în [3 6 9].

Go nu are o metodă map pentru slice-uri. Scrii o buclă care apelează funcția pentru fiecare element și folosește append ca să adauge rezultatul într-un slice nou. Dacă faci asta des, pune bucla într-o funcție helper generică.

Nu confunda acest lucru cu tipul map din Go, care ține perechi cheie:valoare. Aici „map” înseamnă „aplică o funcție fiecărui element”.

Map cu o funcție helper

Helper-ul Map primește un slice și o funcție. Apelează funcția pe fiecare element și returnează un slice nou. Aici înmulțește fiecare număr cu 3.

Prompt
Scrie o funcție helper generică Map care aplică o funcție fiecărui element al unui slice și returnează un slice nou. Folosește-o pe slice-ul 1, 2, 3 ca să înmulțești fiecare număr cu 3 și afișează rezultatul.
Ieșire: program Go și rezultatul capturat
Map with a helper function

Map cu indexul

Uneori contează și poziția unui element. În Go, range îți dă atât indexul, cât și valoarea, așa că o buclă simplă este de ajuns. Aici fiecare valoare este înmulțită cu propriul index.

Prompt
Parcurge cu range slice-ul 1, 2, 3, folosind atât indexul, cât și valoarea. Construiește un slice nou în care fiecare element este valoare * index, apoi afișează-l.
Ieșire: program Go și rezultatul capturat
Map with the index

Sari peste unele rezultate

Uneori unele rezultate trebuie eliminate. Go nu are valori null pentru numere, așa că funcția dată helper-ului returnează două lucruri: rezultatul și un bool care spune dacă acesta trebuie păstrat. Când bool-ul este false, elementul este sărit.

Prompt
Scrie un helper generic MapNotNil care primește o funcție ce returnează o valoare și un bool și păstrează doar rezultatele pentru care bool-ul este true. Folosește-l pe slice-ul 1, 2, 3: sări peste numărul 2 și înmulțește-le pe celelalte cu 3. Afișează rezultatul.
Ieșire: program Go și rezultatul capturat
Skip some results

Transformă cheile unui map

Ca să schimbi cheile unui map, creează un map nou și copiază fiecare intrare cu noua cheie. Aici strings.ToUpper transformă fiecare cheie în majuscule. fmt.Println afișează un map cu cheile sortate, așa că rezultatul are mereu aceeași ordine.

Prompt
Pornește de la un map de la „key1” la 1 și de la „key2” la 2. Construiește un map nou cu aceleași valori, dar cu fiecare cheie transformată în majuscule folosind strings.ToUpper. Afișează noul map.
Ieșire: program Go și rezultatul capturat
Transform map keys

Transformă valorile unui map

Ca să schimbi valorile, faci la fel, dar păstrezi cheia și calculezi o valoare nouă. Aici fiecare valoare crește cu lungimea cheii sale: 1 + len("key1") este 5.

Prompt
Pornește de la un map de la „key1” la 1 și de la „key2” la 2. Construiește un map nou cu aceleași chei, în care fiecare valoare este vechea valoare plus lungimea cheii sale. Afișează noul map.
Ieșire: program Go și rezultatul capturat
Transform map values

Zip

Împerecherea (zip) ia două slice-uri și le împerechează elementele după poziție: primul cu primul, al doilea cu al doilea și așa mai departe. Rezultatul are atâtea perechi câte elemente are slice-ul mai scurt.

Go nu are o funcție zip. Definești un struct mic care ține o pereche, afli lungimea mai mică cu funcția încorporată min și parcurgi cu un index ca să construiești perechile.

Împerechează două slice-uri

Struct-ul Pair ține o culoare și un animal. Bucla merge până la lungimea mai mică și construiește câte un Pair pentru fiecare index. Afișarea unui slice de struct-uri arată fiecare pereche între acolade.

Prompt
Definește un struct Pair cu un câmp Color și un câmp Animal. Combină element cu element slice-urile roșu, maro, gri și vulpe, urs, lup într-un slice de perechi, oprindu-te la slice-ul mai scurt. Afișează slice-ul de perechi.
Ieșire: program Go și rezultatul capturat
Zip two slices

Împerechează cu o transformare

Nu ai nevoie întotdeauna de perechile în sine. Aici bucla folosește direct ambele elemente ca să construiască o propoziție. animals[i][:1] este prima literă, scrisă cu majusculă folosind strings.ToUpper, iar animals[i][1:] este restul cuvântului.

Prompt
Combină element cu element slice-urile roșie, maro, gri și vulpea, ursul, lupul. Pentru fiecare pereche afișează o propoziție de forma „Vulpea este roșie”, cu prima literă a numelui animalului scrisă cu majusculă.
Ieșire: program Go și rezultatul capturat
Zip with a transformation

Desfă un slice de perechi

Desfacerea (unzip) este operația inversă: un slice de perechi devine două slice-uri. Bucla citește fiecare pereche și adaugă părțile ei în două slice-uri separate.

Prompt
Pornește de la un slice de perechi: one cu 1, two cu 2, three cu 3. Împarte-l într-un slice de cuvinte și un slice de numere și afișează fiecare slice pe câte o linie.
Ieșire: program Go și rezultatul capturat
Unzip a slice of pairs

Associate

Asocierea construiește un map dintr-un slice. Fiecare element îți dă o cheie și o valoare. Un map nu poate ține aceeași cheie de două ori, așa că, dacă două elemente produc aceeași cheie, câștigă cel de mai târziu.

Go nu are funcții associate. Creează un map gol cu make, apoi parcurge slice-ul și atribuie result[key] = value pentru fiecare element.

Elementele ca chei

Elementul însuși devine cheie, iar valoarea este calculată din el. Aici cuvintele sunt chei, iar lungimile lor sunt valori.

Prompt
Construiește un map din cuvintele one, two, three, în care fiecare cuvânt este o cheie, iar lungimea lui este valoarea. Afișează map-ul.
Ieșire: program Go și rezultatul capturat
Elements as keys

Elementele ca valori

Elementul devine valoare, iar cheia este calculată din el. Aici cheia este prima literă scrisă cu majusculă. Și two, și three încep cu T, așa că three îl înlocuiește pe two, iar map-ul are doar două intrări.

Prompt
Construiește un map din cuvintele one, two, three, în care cheia este prima literă a cuvântului scrisă cu majusculă, iar valoarea este cuvântul însuși. Afișează map-ul și observă că „three” îl înlocuiește pe „two” la cheia T.
Ieșire: program Go și rezultatul capturat
Elements as values

Calculează și cheia, și valoarea

Poți calcula din element atât cheia, cât și valoarea. Aici cheia este prima literă, iar valoarea este lungimea cuvântului. Din nou câștigă intrarea T de mai târziu.

Prompt
Construiește un map din cuvintele one, two, three, în care cheia este prima literă scrisă cu majusculă, iar valoarea este lungimea cuvântului. Afișează map-ul.
Ieșire: program Go și rezultatul capturat
Compute both key and value

Cheie și valoare dintr-un singur element

Uneori un singur element conține ambele părți. strings.Fields împarte un nume complet la spații într-un slice de cuvinte. Numele de familie devine cheie, iar prenumele devine valoare.

Prompt
Pornește de la numele complete „Alice Adams” și „Brian Brown”. Împarte fiecare nume în cuvinte cu strings.Fields și construiește un map de la numele de familie la prenume. Afișează map-ul.
Ieșire: program Go și rezultatul capturat
Key and value from one element

Flatten

Aplatizarea (flatten) transformă o colecție imbricată, de exemplu un slice de slice-uri, într-un singur slice simplu, cu toate elementele în ordine.

Go nu are o metodă flatten, dar append poate adăuga un slice întreg dintr-o dată: append(result, inner...). Cele trei puncte împrăștie toate elementele din inner în apel.

Aplatizează un slice de slice-uri

Bucla trece prin fiecare slice interior și adaugă toate elementele lui în result. Două slice-uri interioare de câte trei numere devin un singur slice cu șase numere.

Prompt
Pornește de la un slice de slice-uri: 1, 2, 3 și 4, 5, 6. Adaugă toate elementele interioare într-un singur slice plat folosind append cu operatorul ..., apoi afișează-l.
Ieșire: program Go și rezultatul capturat
Flatten a slice of slices

Aplatizează valorile din struct-uri

Un flat map ia mai întâi câte un slice din fiecare element, apoi le unește pe toate. În Go citești câmpul care te interesează, c.Values, și îl adaugi cu cele trei puncte. Toate valorile din cele trei containere ajung într-un singur slice.

Prompt
Definește un struct Container cu un câmp Values care este un slice de string-uri. Creează trei containere care conțin one, two, three; four, five; și six, șapte, opt. Adună toate valorile lor într-un singur slice și afișează-l.
Ieșire: program Go și rezultatul capturat
Flatten values from structs

Reprezentarea ca string

Deseori vrei să arăți o colecție ca text lizibil, de exemplu cu virgule între elemente.

În Go, strings.Join primește un slice de string-uri și un separator și returnează un singur string. Restul — un prefix, un postfix, o limită sau o transformare — se face cu simplă concatenare de string-uri sau cu o buclă scurtă înainte de unire. Numerele trebuie transformate mai întâi în string-uri, de exemplu cu strconv.Itoa.

Unește cu un separator

strings.Join pune ", " între cuvinte și returnează un singur string.

Prompt
Unește cuvintele one, two, three într-un singur string, cu „, ” între ele, folosind strings.Join. Afișează string-ul.
Ieșire: program Go și rezultatul capturat
Join with a separator

Adaugă un prefix și un postfix

Un prefix și un postfix sunt doar text în jurul rezultatului unit. În Go le adaugi cu +.

Prompt
Unește cuvintele one, two, three cu „ | ” între ele, adaugă prefixul „început: ” și postfixul „: sfârșit”, apoi afișează rezultatul.
Ieșire: program Go și rezultatul capturat
Add a prefix and a postfix

Limitează numărul de elemente

Pentru un slice lung poate vrei să arăți doar primele câteva elemente. Ia un slice cu primele 10 folosind numbers[:10], transformă fiecare număr în string cu strconv.Itoa, apoi adaugă "...>" la final ca să arăți că restul elementelor au fost tăiate.

Prompt
Creează un slice cu numerele de la 1 la 100. Unește doar primele 10 dintre ele cu „, ” între ele și adaugă „<...>” la final ca să arăți că lista a fost tăiată. Afișează rezultatul.
Ieșire: program Go și rezultatul capturat
Limit the number of elements

Transformă fiecare element înainte de unire

Ca să schimbi fiecare element înainte de unire, construiește într-o buclă un slice nou de string-uri, apoi apelează strings.Join pe el. Aici fiecare cuvânt devine "Element: " plus cuvântul scris cu majuscule.

Prompt
Transformă fiecare dintre cuvintele one, two, three în „Element: ” urmat de cuvânt scris cu majuscule. Unește rezultatele cu „, ” și afișează string-ul.
Ieșire: program Go și rezultatul capturat
Transform each element before joining