4 votes

Trier une liste de tuples par leur premier indice dans Elm

Supposons que j'ai une liste de tuples qui ressemblent à l'exemple suivant :

[(5, "a"), (1, "c"), (7, "d")] 

dans Elm, comment faire pour trier la liste dans l'ordre croissant de leurs premiers éléments afin d'obtenir le résultat suivant ?

[(1, "c"), (5, "a"), (7, "d")]

Utilisation de la Documentation sur la liste Elm il apparaît que le sortBy y sortWith seront utiles dans ce cas. Ma tentative d'implémentation est la suivante :

maxTuples : Tuple(a, b) -> Tuple(a, b) -> Tuple(a, b)
maxTuples t1 t2 = 
    case compare t1 t2 of 
        ((Tuple.first t1) >= (Tuple.first t2)) -> GT
         _                                     -> LT

sortByFirst : List (Tuple (a, b)) -> List (Tuple (a, b))
sortByFirst lst = 
    List.sortWith maxTuples lst

Cependant, j'obtiens des erreurs de compilation de la nature suivante :

I ran into something unexpected when parsing your code!

99|         ((Tuple.first t1) >= (Tuple.first t2)) -> GT
                ^
I am looking for one of the following things:

an upper case name

Mon intuition me dit que le compilateur recherche GT / LT / EQ par l'API de List mais si c'est le cas, je ne vois pas comment nous pourrions utiliser l'un ou l'autre des éléments suivants sortBy o sortWith pour trier une liste de Tuples dans Elm par le premier indice de chaque élément.

5voto

Jan Tojnar Points 1037

Vous avez trouvé les bonnes fonctions. Dans votre code, il y a en fait plusieurs problèmes :

  1. Les annotations de type doivent être simplement (a, b) pas Tuple(a, b) .
  2. Vous comparez t1 con t2 qui comparera les tuples lexicographiquement. Vous voulez en fait compare (Tuple.first t1) (Tuple.first t2)
  3. En case nécessitent un modèle avant la -> . Dans ce cas, ce serait quelque chose comme EQ puisque vous êtes en correspondance avec le résultat de compare qui renvoie Order type.

Vous pourriez corriger le code comme ceci :

maxTuples : (comparable, b) -> (comparable, b) -> (comparable, b)
maxTuples t1 t2 = 
    case compare (Tuple.first t1) (Tuple.first t2) of 
        GT -> GT
        EQ -> EQ
         _ -> LT

Mais maintenant il y a une répétition inutile, vous retournez simplement le résultat de compare fonction.

maxTuples t1 t2 = 
    compare (Tuple.first t1) (Tuple.first t2)

Avec la fonction de tri, cela ressemblerait à ceci :

sortByFirst lst = 
    List.sortWith (\t1 t2 -> compare (Tuple.first t1) (Tuple.first t2)) lst

Il s'avère que ce type d'opération est assez courant, notamment avec les listes d'enregistrements. Pour cette raison, Elm propose une autre fonction - sortBy . Il prend une fonction et compare les éléments après avoir appliqué la fonction :

sortBy f lst =
    List.sortWith (\a b -> compare (f a) (f b)) lst

Vous pouvez donc utiliser sortBy pour simplifier considérablement le code :

sortByFirst : List (comparable, b) -> List (comparable, b)
sortByFirst =
    sortBy Tuple.first

4voto

pdamoc Points 1433

Il convient de noter que ce que vous souhaitez est le comportement par défaut de l'option List.sort (le tri utilisera le premier élément du tuple pour ordonner la liste et si deux éléments ont le même premier élément, il passera à la comparaison du second et ainsi de suite) List.sort [(5, "a"), (1, "c"), (1, "a"), (7, "d")] == [(1,"a"),(1,"c"),(5,"a"),(7,"d")]

L'utilisation de sortBy dans ce cas est redondante.

0voto

bdukes Points 54833

Je ne suis pas sûr de ce que compare est en case compare t1 t2 of mais vous pouvez simplement utiliser une ligne droite if au lieu d'un case (et utiliser également la déstructuration au lieu de Tuple.first si vous préférez) :

maxTuples ( val1, _ ) ( val2, _ ) =
    if val1 >= val2 then
        GT
    else
        LT

J'ai un exemple complet et fonctionnel à https://ellie-app.com/ZZ9Hzhg7yva1/2 (il y a aussi eu quelques changements d'annotation de type qui ont dû être faits pour que cela compile).

Cependant, sortBy est l'option la plus simple, car elle peut simplement prendre Tuple.first pour trier par ce qui est là-dedans :

sortByFirst lst =
    List.sortBy Tuple.first lst

Cette version se trouve à l'adresse suivante https://ellie-app.com/ZZ9Hzhg7yva1/3

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X