Maison >développement back-end >Golang >L'ordre `sort.Slice` n'est pas défini

L'ordre `sort.Slice` n'est pas défini

王林
王林avant
2024-02-10 12:12:101138parcourir

`sort.Slice` 顺序是不确定的

l'éditeur php Strawberry vous présentera quelques informations importantes sur la fonction `sort.Slice`. En langage Go, la fonction `sort.Slice` est utilisée pour trier les tranches, mais l'ordre de ses résultats triés n'est pas défini. Autrement dit, pour une même tranche d’entrée, les résultats du tri peuvent être différents à chaque fois. En effet, la fonction « sort.Slice » utilise un algorithme de tri rapide et efficace, mais l'ordre spécifique de tri est basé sur des conditions spécifiques des données d'entrée. Par conséquent, lors de l'utilisation de la fonction « sort.Slice », nous devons être conscients du non-déterminisme des résultats du tri pour éviter les problèmes dans les scénarios qui reposent sur un ordre de tri spécifique.

Contenu de la question

J'essaie d'utiliser sort.slice 对字符串切片进行排序。我希望它们按字母顺序排序,除了我希望空字符串出现在所有其他字符串之后(因此我不能只使用 sort.strings) de la bibliothèque standard Go.

Pour le moins de fonctions, je pense que cela fonctionnerait :

func(i, j int) bool {
    return s[j] == "" || s[i] < s[j]
}

Cependant, il semble que j'obtienne des réponses aléatoires en fonction de l'ordre d'entrée. C'est mwe :

package main

import (
    "fmt"
    "math/rand"
    "sort"
    "time"
)

func main() {
    s := []string{"", "foo", "bar", "baz"}

    rand.seed(time.now().unix())
    rand.shuffle(len(s), func(i, j int) {
        s[i], s[j] = s[j], s[i]
    })
    fmt.printf("%q\n", s)

    sort.slice(s, func(i, j int) bool {
        return s[j] == "" || s[i] < s[j]
    })
    fmt.printf("%q\n", s)
}

Voici le résultat de l'exécution plusieurs fois :

$ go run ./z
["" "foo" "baz" "bar"]
["bar" "baz" "foo" ""]
$ go run ./z
["baz" "" "foo" "bar"]
["bar" "" "baz" "foo"]
$ go run ./z
["bar" "foo" "" "baz"]
["" "bar" "baz" "foo"]
$ go run ./z
["bar" "foo" "baz" ""]
["" "bar" "baz" "foo"]

Solution de contournement

C'est parce que votre fonction less() ne dit pas ce que vous voulez.

Vous avez dit que vous souhaitiez que la chaîne vide soit triée après toutes les chaînes non vides. Votre logique :

return s[j] == "" || s[i] < s[j]

Cela nous indique si le second est "",那么第一个就更少。这或多或少是正确的(除非两者都是空的,“is-less”并不是真的:它们是相等的)。但是,如果第一个是 "" 而第二个不是怎么办?那么你的函数应该返回 false 但它返回 s[i] < s[j]。如果第二个不为空,则为 true,告诉 "" plus petit que l'autre, ce qui est exactement le contraire de ce que vous souhaitez.

La relation correcte "est-moins" est la suivante :

sort.slice(s, func(i, j int) bool {
    if s[j] == "" && s[i] != "" {
        return true
    }
    if s[i] == "" && s[j] != "" {
        return false
    }
    return s[i] < s[j]
})

Si seulement le second est "", vous voulez que le premier soit inférieur. Si seul le premier est vide, vous voulez qu'il soit "pas moins que". Sinon, l'ordre normal (par octet) est utilisé.

Essayez-le sur le go terrain de jeu.

Notez que si les première et deuxième valeurs sont vides, cette fonction renverra false car false,因为 "" 不小于 "" (它们相等)。这是要返回的正确值,尽管在此处返回 true n'est pas inférieur à

(elles sont égales). C'est la valeur correcte à renvoyer, bien que renvoyer true ici entraînera toujours l'ordre correct (l'échange d'éléments vides entraînera le même résultat), mais cela peut entraîner moins d'échanges.

Utilisez la logique de transformation xor

Veuillez noter que dans la logique personnalisée, si une seule chaîne est vide, elle s'écartera de l'ordre normal. C'est la relation logique XOR (XOR)a xor btrue 如果只有 a 或只有 btrue。在 go 中,没有逻辑 xor 运算符,但 a xor b 相当于 a != b :

.

true(否则为 falseSi une chaîne vide est "détectée", le résultat est

si la deuxième chaîne vide est vide). Nous pouvons donc appliquer cette transformation identitaire à notre logique :

sort.Slice(s, func(i, j int) bool {
    // Move empty elements to the end:
    if (s[i] == "") != (s[j] == "") { // If only one is empty
        return s[j] == ""
    }
    return s[i] < s[j]
})
C'est plus court et probablement plus efficace, mais comme vous pouvez le voir, c'est plus difficile à comprendre. Utilisez cette option uniquement si les performances sont importantes. Essayez ceci sur le go terrain de jeu

. 🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer