排序一个列表由另一个列表的顺序

问题描述 投票:10回答:2

我需要别人的顺序排序一个列表,但我不知道它是如何完成的。

例如:我有一个列表a类似于:

[C, B, G, E]

和列表b(即设置顺序):

[A, B, C, D, E, F, G, ...]

(正如例如,这些都不是实际值虽然)

然后,名单a应该排序方式列表b相同,从而成为分拣到:

[B, C, E, G]

如何通过另一个列表的顺序做这个排序?

sorting haskell
2个回答
4
投票

如果我的理解,该列表中的一个给其他列表中的所有元素的相对顺序。即:

 > sortWithOrder [5,1,2,3,4] [1,2,3,4,5,5,4,3,2,1]
 [5,5,1,1,2,2,3,3,4,4]

这段代码应工作:

module SortWithOrder where

import qualified Data.Map.Strict as M
import Data.List
import Data.Ord

sortWithOrder :: Ord a
              => [a] -- order list
              -> [a] -- source list
              -> [a]
sortWithOrder order = sortBy (comparing getOrder)
    where
        getOrder k = M.findWithDefault (-1) k ordermap
        ordermap = M.fromList (zip order [0..])

编辑:更高效的解决方案是使用sortOn,就像这样:

sortWithOrder order = sortOn getOrder

3
投票

您也可以在命令映射到列表和排序是:

Prelude> let order = zip ["A", "B", "C", "D", "E", "F", "G"] [0..]

Prelude> let myList = ["C", "B", "G", "E"]

Prelude> import Data.List (sort)

Prelude> map snd . sort . map (\x -> (lookup x order, x)) $ myList

["B","C","E","G"]

因此,我们可以定义此功能

sortAlong :: Eq b => [b] -> [b] -> [b]
sortAlong order = map snd . sortBy (comparing fst) . map (\x -> (lookup x z, x))
    where
    z = zip order [0..]

一个Ord约束允许更有效的路线,通过Map不过这个版本需要只是Eq

> sortAlong "ABCDEFG" "CBGE"
"BCEG"
© www.soinside.com 2019 - 2024. All rights reserved.