sorting lists using sortBy

前端 未结 2 1404
天命终不由人
天命终不由人 2021-01-21 22:13

I am trying to sort my list of tuples based on the 4th element in each of the tuples. The fourth element contains a string that is a person\'s name. I want to put tuples that c

相关标签:
2条回答
  • 2021-01-21 23:01

    Start with the type of sortBy:

    > :t sortBy
    sortBy :: (a -> a -> Ordering) -> [a] -> [a]
    

    This means byName needs to have type a -> a -> Ordering. In this case, a is a tuple whose fifth element as type String; byName will ignore the other fields. So you'll need to define a function like

    type MyType = (String, Int, String, Int, String, Double)
    byName :: MyType -> MyType -> Ordering
    byName (_, _, _, _, a, _) (_, _, _, _, b, _) = ...
    

    I leave replacing the ... with the correct expression as an exercise.

    (Recall that Ordering is a type with three values, LT, EQ, and GT, where byName a b == LT if a < b, byName a b == EQ if a == b, and byName a b == GT if a > b. In your case, two tuples will compare as equal as long as they have the same name. It sounds like you don't actually care whether byName returns LT or GT otherwise.)

    0 讨论(0)
  • 2021-01-21 23:02

    While you can figure something like this out for yourself, most of the desired capability is already available via Data.Ord. If tuples is your input list, you can just use:

    sortBy (comparing name) tuples
    

    where name is a utility function defines as:

    name (_, _, _, _, n, _) = n
    

    This is actually a parametrically polymorphic function, so you could also call it fifth, or something generic like that.

    You can call the above expression and format the output to see that it does approximately what you want:

    Prelude Data.Ord Data.List> putStrLn $ unlines $ show <$> sortBy (comparing name) tuples
    ("B",101,"M",3,"Jon",3.33)
    ("B",273,"F",1,"Mike",2.66)
    ("B",203,"R",3,"Rachel",1.66)
    ("A",200,"P",1,"Rachel",0.0)
    ("A",999,"N",3,"Rachel",1.33)
    ("A",100,"Q",3,"Todd",2.0)
    ("A",549,"D",3,"Todd",2.0)
    ("B",220,"S",3,"Todd",4.0)
    

    Compared to the OP, this is in the opposite order of what's required, but I'll leave it as an exercise to figure out how to change the sort order. There's a couple of different ways to do that.

    0 讨论(0)
提交回复
热议问题