我有一個元組串列,我想按第二個元素(降序)然后按第一個元素(升序)對其進行排序。
我的代碼如下所示:
sortedOcc :: Eq a => [a] -> [(a, Int)]
sortedOcc = sortBy (flip compare `on` snd) . occurences
這是occurences(函式)回傳的串列的第二個元素的第一次排序。我應該如何通過第一個元素添加第二個排序(升序)?
uj5u.com熱心網友回復:
該Data.Ord模塊提供了一個Down新型別,其目的僅僅是為了顛倒排序。
它還提供了一個comparing功能:
comparing :: Ord a => (b -> a) -> b -> b -> Ordering
必須先輸入一些轉換函式,然后才能將其傳遞給sortBy.
像這樣:
$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
λ>
λ> sortBy (comparing (\(a,v) -> (Down v, a))) [(1,2),(1,3),(5,2),(5,3)]
[(1,3),(5,3),(1,2),(5,2)]
λ>
然后,轉換函式回傳的值使用它們自己的“自然”順序進行排序。在我們的例子中,這是成對的有序型別的字典順序。
總的來說,代碼需要一個Ord a約束:
sortedOcc :: Ord a => [a] -> [(a, Int)]
sortedOcc = sortBy (comparing (\(a,v) -> (Down v, a))) . occurences
uj5u.com熱心網友回復:
我可能會在函式型別上使用實體MonoidOrdering來撰寫它。
flip compare `on` snd正如您已經確定的那樣,對元組中的第二個值進行排序看起來像,而對第一個值進行排序看起來像compare `on` fst。這些可以與 Monoidally 組合<>。
d :: [(String , Int)]
d = [("b", 1), ("a", 1), ("c",3), ("d",4)]
sortedD = sortBy ((flip compare `on` snd) <> (compare `on` fst)) d
uj5u.com熱心網友回復:
我知道其余的答案都比較短,但我建議你在使用已經實作的 Haskell 函式之前自己實作這些惰性函式,這樣你就可以理解它是如何作業的。
-- Order a list of tuples by the first item
orderBy1stTupleItem :: Ord a => (a, b1) -> (a, b2) -> Ordering
orderBy1stTupleItem tup1 tup2
| item1 > item2 = GT
| item1 < item2 = LT
| otherwise = EQ
where
item1 = fst tup1
item2 = fst tup2
-- Order a list of tuples by the second item
orderBy2ndTupleItem :: Ord a1 => (a2, a1) -> (a3, a1) -> Ordering
orderBy2ndTupleItem tup1 tup2
| item1 > item2 = GT
| item1 < item2 = LT
| otherwise = EQ
where
item1 = snd tup1
item2 = snd tup2
-- Wrapper Function: Order a list of tuples by the first item and later by the second item
orderTuplesBy1stThenBy2ndItem :: (Ord a1, Ord a2) => [(a2, a1)] -> [(a2, a1)]
orderTuplesBy1stThenBy2ndItem listTuples =
sortBy orderBy2ndTupleItem (sortBy orderBy1stTupleItem listTuples)
例子
let exampleListTuples = [(1,2),(0,8),(6,1),(3,6),(9,1),(7,8),(0,9)]
然后讓我們得到第一個串列,按每個元組的第一項排序:
> listOrderedByTuple1stItem = sortBy orderBy1stTupleItem exampleListTuples
> listOrderedByTuple1stItem
[(0,8),(0,9),(1,2),(3,6),(6,1),(7,8),(9,1)]
現在我們按每個元組的第二項對這個結果串列進行排序
> sortBy orderBy2ndTupleItem listOrderedByTuple1stItem
[(6,1),(9,1),(1,2),(3,6),(0,8),(7,8),(0,9)]
或者,您可以orderTuplesBy1stThenBy2ndItem按如下方式運行包裝函式:
> sortBy orderTuplesBy1stThenBy2ndItem exampleListTuples
uj5u.com熱心網友回復:
什么是 sortBy簽名?
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
這意味著它的第一個引數必須具有型別a -> a -> Ordering:
sortedOcc :: Eq a => [a] -> [(a, Int)]
sortedOcc = sortBy g . occurences
g :: a -> a -> Ordering
g = (flip compare `on` snd)
但這意味著
g :: a -> a -> Ordering
g x y = (flip compare `on` snd) x y
= flip compare (snd x) (snd y)
= compare (snd y) (snd x)
因此,要將您的要求添加到組合中,我們只需將其寫下來,
= let test1 = compare (snd y) (snd x)
test2 = compare (snd y) (snd x)
in ......
對?
上面故意包含錯誤,您應該可以直接修復。
一個忠告,如果您可以輕松自然地閱讀、撰寫和修改.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/474038.html
