Как итерироваться по элементам map в отсортированном порядке (по ключам или значениям)?

Ответ

Важно понимать, что map в Go является неупорядоченной коллекцией. Порядок итерации по ее элементам не гарантируется и может меняться при каждом запуске программы. Чтобы получить элементы в отсортированном виде, необходимо выполнить несколько шагов.

1. Сортировка по ключам

Это самый распространенный сценарий. Алгоритм следующий:

  1. Создать срез для хранения ключей из map.
  2. Скопировать все ключи в этот срез.
  3. Отсортировать срез ключей с помощью пакета sort.
  4. Итерироваться по отсортированному срезу ключей, получая значения из map.
package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[string]int{"c": 3, "a": 1, "b": 2}

    keys := make([]string, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }
    sort.Strings(keys) // Сортируем ключи

    for _, k := range keys {
        fmt.Printf("Ключ: %s, Значение: %dn", k, m[k])
    }
    // Вывод:
    // Ключ: a, Значение: 1
    // Ключ: b, Значение: 2
    // Ключ: c, Значение: 3
}

2. Сортировка по значениям

Этот подход немного сложнее. Нужно создать структуру для хранения пар ключ-значение, скопировать в нее данные из map и отсортировать срез этих структур.

package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[string]int{"Go": 95, "Rust": 98, "Python": 85}

    type kv struct {
        Key   string
        Value int
    }

    var ss []kv
    for k, v := range m {
        ss = append(ss, kv{k, v})
    }

    sort.Slice(ss, func(i, j int) bool {
        return ss[i].Value < ss[j].Value // Сортируем по значению
    })

    for _, pair := range ss {
        fmt.Printf("Ключ: %s, Значение: %dn", pair.Key, pair.Value)
    }
    // Вывод:
    // Ключ: Python, Значение: 85
    // Ключ: Go, Значение: 95
    // Ключ: Rust, Значение: 98
}

Ответ 18+ 🔞

Смотри, ну вот объясняю тебе как есть, блядь. Мапа в Go — это такая неупорядоченная свалка, ёпта. Порядок там, сука, как карта ляжет, и каждый раз по-новому может вылезти, просто пиздец. Хочешь красоты и порядка? Придётся, блядь, попотеть.

1. Сортировка по ключам (самый частый геморрой)

Алгоритм, блядь, простой, как три копейки, но без него нихуя не выйдет:

  1. Берёшь срез, сука, под ключи.
  2. Запихиваешь туда все ключи из мапы, как в мусорный мешок.
  3. Сортируешь этот срез ключей, используя sort. Ну, чтобы по алфавиту или числам.
  4. Идешь по отсортированным ключам и вытаскиваешь из мапы значения, как из кармана.
package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[string]int{"c": 3, "a": 1, "b": 2}

    keys := make([]string, 0, len(m))
    for k := range m {
        keys = append(keys, k)
    }
    sort.Strings(keys) // Вот тут ключи и становятся паиньками

    for _, k := range keys {
        fmt.Printf("Ключ: %s, Значение: %dn", k, m[k])
    }
    // Вывод:
    // Ключ: a, Значение: 1
    // Ключ: b, Значение: 2
    // Ключ: c, Значение: 3
}

2. Сортировка по значениям (тут уже посложнее, хитрая жопа)

Тут уже надо головой думать, блядь. Надо создать структуру, чтобы пары ключ-значение хранить, потом всё туда скопировать и этот срез структур отсортировать.

package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[string]int{"Go": 95, "Rust": 98, "Python": 85}

    type kv struct {
        Key   string
        Value int
    }

    var ss []kv
    for k, v := range m {
        ss = append(ss, kv{k, v})
    }

    sort.Slice(ss, func(i, j int) bool {
        return ss[i].Value < ss[j].Value // Смотри, сортируем уже по значению, а не по ключу!
    })

    for _, pair := range ss {
        fmt.Printf("Ключ: %s, Значение: %dn", pair.Key, pair.Value)
    }
    // Вывод:
    // Ключ: Python, Значение: 85
    // Ключ: Go, Значение: 95
    // Ключ: Rust, Значение: 98
}

Вот и вся магия, блядь. Запомни: мапа сама по себе — хаос, а порядок надо создавать руками, в рот меня чих-пых.