相对于另一个列表排序多图?

时间:2011-12-28 12:21:02

标签: list sorting haskell multimap

给定一定的键顺序,如何对这个列表排序多图(带有重复键的元组列表),其中重复元素的顺序无关紧要?

我正在寻找具有以下签名的功能

sortByList :: [(a,b)] -> [a] -> [(a,b)]

这样,例如,

a = [(1,'a'), (2, 'b'), (102, 'c'), (2, 'z')]
b = [2,102,1]
sortByList a b   --    [(2,'b'), (2,'z'), (102, 'c'), (1, 'a')]
                 -- or [(2,'z'), (2,'b'), (102, 'c'), (1, 'a')] 
                 -- (order in duplicate keys irrelevant)

我有一些想法如何实现这一点,但它们看起来都很丑陋和繁琐(使用lookup并在给定的多图上重复查找和删除)。

4 个答案:

答案 0 :(得分:6)

我认为这应该是相当优化的:

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

sortByList :: Ord a => [(a, b)] -> [a] -> [(a, b)]
sortByList xs ys = map snd $ sortBy (comparing fst) [(pos (fst x), x) | x <- xs]
  where order = M.fromList $ zip ys [1..]
        pos x = M.findWithDefault 0 x order

如果xs的长度 n ys的长度 m ,则运行时间应为 O(n log) n +(m + n)log m),如果 m O(n),则 O(n log n) >

答案 1 :(得分:4)

elemIndex是您需要的功能:

import Data.List (sortBy, elemIndex)
import Data.Function (on)

sortByList :: Eq a => [(a,b)] -> [a] -> [(a,b)]
sortByList m as = sortBy (compare `on` (flip elemIndex as . fst)) m

它将不在列表中的键放在前面,因为Nothing < Just 0

答案 2 :(得分:0)

这是一个远非最佳建议:

import Data.List

sortByList :: (Eq a) => [(a,b)] -> [a] -> [(a,b)]
sortByList toSort order = reverse (go [] toSort order)
    where
      go result xs [] = xs ++ result
      go result xs (k:ks) = go (matches ++ result) unmatches ks
          where
            (matches, unmatches) = partition ((==k) . fst) xs

答案 3 :(得分:0)

import Data.List 
sortByList::(Ord a,Ord b)=>[(a,b)]->[a]->[(a,b)]
sortByList m [] = m
sortByList m (x:xs) = sort(filter (\(a,b)->a==x) m)++ sortByList (filter (\(a,b)->a/=x) m) xs

丑陋的代码,但它的工作原理

import Data.List 
sortByList::(Ord a,Ord b)=>[(a,b)]->[a]->[(a,b)]
sortByList m [] = m
sortByList m (x:xs) = let t = filter (\(a,b)->a==x) m in sort t ++ sortByList (m\\t) xs