If I just have a very simple custom data type:
data Person = Person {first_name :: String,
last_name :: String
} deriving (Ord, Eq, Show)
If I have a list of these Person data types, and I want to sort it by last_name
if and only if the first_name
is the same. But I should not sort the first_name
. Simply call the following obviously doesn't work.
import Data.Function (on)
import Data.List (sortBy)
sortBy (compare `on` last_name ) persons
How can I solve it? I do agree it's quite confusing. What I want is that if I have the following (that's definitely not a list of the custom data type, I just want to show it clearly)
[("c","d"),("a","c"),("a","a")]
After sorting I would like to have
[("c","d"),("a","a"),("a","c")]
instead of
[("a","a"),("a","c"),("c","d")]
So the idea is that first element should still appear at first, since it does not have the same first_name
with the other two. Is that possible? Thanks!
The comparison function you want is to treat two Person
values as equal if their first names are different. If the first names are the same, then compare based on the last name.
Since sort
in Haskell is stable, if an element a
precedes an equal element b
in the input, it will also precede b
in the output. In this case, two elements with different first names will compare as equal, so sort
will really only sort the consecutive subsequences sharing a first name.
There is probably a clever way to implement this, but a straightforward comparison function might look like
foo :: Person -> Person -> Ordering
foo x y | first_name x /= first_name y = EQ
| otherwise = (comparing last_name) x y
Given people = [ Person "A" "B",Person "Z" "C",Person "Z" "A"]
, you can see the difference between sortBy (comparing last_name)
and sortBy foo
.
> people
[Person {first_name = "A", last_name = "B"},Person {first_name = "Z", last_name = "C"},Person {first_name = "Z", last_name = "A"}]
> sortBy (comparing last_name) people
[Person {first_name = "Z", last_name = "A"},Person {first_name = "A", last_name = "B"},Person {first_name = "Z", last_name = "C"}]
> sortBy foo people
[Person {first_name = "A", last_name = "B"},Person {first_name = "Z", last_name = "A"},Person {first_name = "Z", last_name = "C"}]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.