Yerleşik tipleri sıralamak
slices.Sort, eleman tipi sıralanabilir olan her slice'ı sıralar: tam sayılar, float'lar ve string'ler. Yerinde sıralar ve hiçbir şey döndürmez.
Çıktı:
[3 7 19 42 88]
[Bob Carl alice lisa]
true
2 true
String'ler baytlara göre sıralanır, bu yüzden her büyük ASCII harfi her küçük harften önce gelir. Adlar için bir kullanıcının beklediği nadiren budur. Bir sonraki bölüm bunu düzeltiyor.
slices paketi Go 1.21'de geldi. Sort'u bir pattern-defeating quicksort'tur: O(n log n), yerinde ve kararlı değil.
SortFunc ile özel sıra
slices.SortFunc bir karşılaştırma fonksiyonu func(a, b T) int alır. a önce gelmeliyse negatif, b önce gelmeliyse pozitif, eşitlerse sıfır döndürün. cmp.Compare yardımcısı sıralanabilir tipler için tam olarak bunu döndürür.
Bir karşılaştırmanın içindeki strings.ToLower, girdisinde büyük harf olduğunda her seferinde yeni bir string ayırır ve karşılaştırma yaklaşık n log n kez çalışır. Büyük slice'lar için küçük harfli anahtarları bir kez hesaplayın. Başka dillerdeki adlar (aksanlar, yerel ayar kuralları) için standart kütüphanenin dışındaki golang.org/x/text/collate'i kullanın.
Bir karşılaştırma fonksiyonu tutarlı olmalıdır: a'nın b'den önce geldiğini söylüyorsa b'nin a'dan sonra geldiğini de söylemelidir. Bunu bozan bir fonksiyon (örneğin iki değer farklı olduğunda her zaman -1 döndüren) hiçbir hata vermeden yanlış sıralanmış bir slice üretir. Tam sayıları çıkarmak (return a - b) şık görünür ama büyük değerlerde taşar; cmp.Compare kullanın.
Struct'ları sıralamak
Karşılaştırma fonksiyonu elemanları alır, bu yüzden struct'ları bir alana göre sıralamak aynı çağrıdır:
Maaşları eşit olan çalışanlar burada herhangi bir sırayla çıkabilir, çünkü SortFunc kararlı değildir. Garantili bir sıraya ihtiyacınız varsa eşitlikleri daha fazla alanla bozun ya da kararlı bir sıralama kullanın.
Birden fazla alana göre sıralamak
En önemli alanı önce karşılaştırın ve yalnızca eşitlikte bir sonrakine geçin. cmp.Or (Go 1.22) sıfır olmayan ilk argümanını döndürür, bu da bunu tek bir satıra çevirir:
Çıktı:
eng 150 Cy
eng 120 Ana
eng 120 Eve
sales 90 Bob
sales 90 Dee
Düz argümanlar oldukları için ilki karar verse bile her karşılaştırma değerlendirilir. Alan karşılaştırmaları için bunun maliyeti azdır. Bir eşitlik bozucu pahalıysa if c := ...; c != 0 { return c } zincirini elle yazın.
Kararlı sıralama
Kararlı bir sıralama, eşit karşılaştırılan elemanları orijinal sıralarında tutar. Girdinin zaten anlamlı bir sırası olduğunda bu önemlidir; örneğin zamana göre sıralanmış ve şimdi kullanıcıya göre grupladığınız kayıtlar.
Bu [{ana 2} {ana 4} {bob 1} {bob 3} {bob 5}] yazdırır: her kullanıcının içinde orijinal dizilim korunur. Kararlı sıralama daha fazla iş yapar, bu yüzden onu yalnızca eşit elemanların sırası önemli olduğunda kullanın.
Bir map'i sıralamak
Map'lerin sırası yoktur. Bir map'i anahtara göre sıralı göstermek için anahtarlarını sıralayın: slices.Sorted(maps.Keys(m)) (Go 1.23). Değere göre sıralamak için anahtarları değerlere bakan bir karşılaştırmayla sıralayın:
Kelimeye göre eşitlik bozmak önemlidir: o olmadan chan ve slice (ikisi de 7) çalıştırmadan çalıştırmaya farklı sırayla yazdırılırdı, çünkü anahtarlar map'ten rastgele sırayla çıkar. Daha fazlası için map'ler sayfasına bakın.
sort paketi: sort.Slice ve diğerleri
Go 1.21'den önce sıralama sort paketi üzerinden yapılıyordu. Var olan birçok kodda onu göreceksiniz:
sort.Ints(nums)
sort.Strings(names)
sort.Slice(staff, func(i, j int) bool {
return staff[i].Salary < staff[j].Salary
})
sort.SliceStable(staff, func(i, j int) bool { ... })
Bilmeye değer farklar:
sort.Slice | slices.SortFunc | |
|---|---|---|
| Fonksiyonun aldığı | indeksler i, j | elemanlar a, b |
| Döndürdüğü | bool (i, j'den küçük mü) | int (negatif, sıfır, pozitif) |
| Tip güvenliği | any alır, reflection kullanır | generic, derleme zamanında kontrol edilir |
| Hız | daha yavaş | daha hızlı |
Yaygın bir sort.Slice hatası, less fonksiyonu konuma göre indekslediği için sıralanandan farklı bir slice'ı yakalamaktır. SortFunc size elemanları verdiği için bu hataya sahip olamaz.
sort.Interface tipi (Len, Less, Swap) en eski biçimdir. Birlikte hareket etmesi gereken iki paralel slice gibi tek bir slice olmayan veriyi sıralamanın yolu hâlâ odur. Go 1.22'den beri sort.Ints, sort.Strings ve sort.Float64s basitçe slices.Sort'u çağırır.
Sık yapılan hatalar
Sort'un sıralanmış slice'ı döndürmesini beklemek. Yerinde sıralar ve hiçbir şey döndürmez. Yeni bir sıralı slice istiyorsanızslices.Sorted(slices.Values(s))kullanın ya da önceslices.Cloneyapın.- Eşit elemanların sıralarını koruduğunu varsaymak. Bunu yalnızca
Stableçeşitleri vaat eder. - Karşılaştırmak için çıkarma yapmak.
a - btaşar.cmp.Comparekullanın. - NaN içeren float'ları sıralamak.
cmp.Compare, NaN'ı diğer her değerden önce sıralar ve bu da sıralamayı tutarlı tutar. Elle yazılmış bira < bkarşılaştırması bunu yapmaz.
Sıkça Sorulan Sorular
Go'da bir slice nasıl sıralanır?
Sayılar ve string'ler için slices.Sort(s) (Go 1.21) çağırın. Yerinde ve artan sırada sıralar. Başka her şey ya da farklı bir sıra için slices.SortFunc(s, func(a, b T) int { ... }) kullanın; fonksiyon a önce geliyorsa negatif, b önce geliyorsa pozitif, eşitlerse sıfır döndürür.
Go'da bir slice azalan sırada nasıl sıralanır?
Karşılaştırmadaki argümanların yerini değiştirin: slices.SortFunc(s, func(a, b int) int { return cmp.Compare(b, a) }). Ya da artan sırada sıralayıp ardından slices.Reverse(s) çağırın.
Go'da struct slice'ı birden fazla alana göre nasıl sıralanır?
İlk alanı karşılaştırın ve yalnızca eşit olduğunda bir sonrakine geçin. cmp.Or (Go 1.22) tam olarak bunu yapar: return cmp.Or(cmp.Compare(a.Dept, b.Dept), cmp.Compare(b.Salary, a.Salary), strings.Compare(a.Name, b.Name)) sıfır olmayan ilk sonucu döndürür.
sort.Slice ile slices.SortFunc arasındaki fark nedir?
sort.Slice(s, func(i, j int) bool) eski API'dir: indeksler üzerinde bir less fonksiyonu alır ve elemanları değiştirmek için reflection kullanır. slices.SortFunc(s, func(a, b T) int) generic'tir, tipleri kontrol edilir, elemanları doğrudan alır ve daha hızlıdır. Yeni kod slices paketini kullanmalıdır; sort.Slice Go 1.21'den önce yazılmış kodda hâlâ yaygındır.