Haskell中的自定义排序

Haskell中的自定义排序,haskell,Haskell,第二次更新: 最后,我按照zurgl的建议写了递归遍历和分组。感谢所有试图帮助你的人 第一次更新: 我所希望的是一个排序函数,但不确定的是,它的目的是优化随后的分组(最小化组的数量)。分组收集水平或垂直相邻的元组: f xs = foldr (\a@(y,x) ((b@(y',x'):xs):bs) -> if (y == y' && abs (x-x') == 1) || (x

第二次更新:

最后,我按照zurgl的建议写了递归遍历和分组。感谢所有试图帮助你的人

第一次更新:

我所希望的是一个排序函数,但不确定的是,它的目的是优化随后的分组(最小化组的数量)。分组收集水平或垂直相邻的元组:

f xs = 
  foldr (\a@(y,x) ((b@(y',x'):xs):bs) -> if (y == y' && abs (x-x') == 1) || 
                                            (x == x' && abs (y-y') == 1)
                                            then (a:b:xs):bs 
                                            else [a]:(b:xs):bs) 
                                            [[last xs]] (init xs)
第二个示例的输出,在“排序”之后:

--更新结束--

我在构思排序函数时遇到了困难,我希望有人能想到如何实现它,或者说是否需要比自定义排序更多的功能。我试过玩弄sortBy,但似乎没有什么进展

我如何从中获得:

[(0,1),(0,3),(1,1),(1,3),(2,0),(2,1),(2,3),(4,1),(4,2)]
为此:

[(0,1),(1,1),(2,0),(2,1),(0,3),(1,3),(2,3),(4,1),(4,2)]
y'和x'之间的差值0或1应为主要值。这有意义吗

第二个例子:

[(0,1),(0,3),(1,1),(1,3),(2,1),(2,2),(2,3),(4,1),(4,2)] 
=>
[(0,1),(1,1),(2,1),(2,2),(2,3),(1,3),(0,3),(4,1),(4,2)]

我的哈斯凯尔已经生锈了,但这应该可以

subsortGT a, b
  | a <= b = GT
  | a > b = LT

sortGT (a1, b1) (a2, b2)
  | a1 + b1 < a2 + b2 = GT
  | a1 + b1 > a2 + b2 = LT
  | a1 + b1 ==  a2 + b2= subsortGT a1 a2

sortBy sortGT [(0,1),(0,3),(1,1),(1,3),(2,0),(2,1),(2,3),(4,1),(4,2)]
substrtgt a、b
|a b=LT
sortGT(a1,b1)(a2,b2)
|a1+b1a2+b2=LT
|a1+b1==a2+b2=a1-a2下部间隙
sortBy sortGT[(0,1)、(0,3)、(1,1)、(1,3)、(2,0)、(2,1)、(2,3)、(4,1)、(4,2)]

利用元组进行排序

import Data.Ord (comparing)
import Data.List (sortBy)

customSort = sortBy (comparing (\(x,y) -> (x+y, abs (x-y))))
或箭头指向自由点(无点)


尝试定义自定义数据类型及其指定顺序。
我建议你这样做

data MPair a = MPair a a deriving (Show)

-- some helper to test
toTuple (MPair x y) = (x, y)
fromX x = MPair x x

instance (Eq a) => Eq (MPair a) where
    (MPair a b) == (MPair c d) = (a == c) && (b == d)

-- This is not exactly the ordering you are looking for
-- But at this stage it should no be a pain to define 
-- the required ordering, you just have to implement it below
instance (Ord a) => Ord (MPair a) where
    compare p@(MPair a b) q@(MPair c d)
            | p == q = EQ
            | otherwise = case (compare a c, compare b d) of  
                            (LT, _) -> LT
                            (_, LT) -> LT
                            _       -> GT

-- convert a list of tuple to a list or MPair.  
fromListToMPair :: [(a,a)] -> [MPair a]
fromListToMPair [] = []
fromListToMPair ((a, b):xs) = (MPair a b) : fromListToMPair xs

-- the inverse of the previous one   
fromMPairToList :: [MPair a] -> [(a,a)] 
fromMPairToList [] = []
fromMPairToList ((MPair a b):xs) = (a, b) : fromMPairToList xs

-- A test case
testList = [(0,1),(0,3),(1,1),(1,3),(2,0),(2,1),(2,3),(4,1),(4,2)]
到ghci进行测试

>>> fromMPairToList $ sort $ fromListToMPair testList
[(0,1),(0,3),(1,1),(1,3),(2,0),(2,1),(2,3),(4,1),(4,2)]
-- add a test to check the stability of your order.  
>>> fromMPairToList $ sort $ sort $ fromListToMPair testList 
[(0,1),(0,3),(1,1),(1,3),(2,0),(2,1),(2,3),(4,1),(4,2)]
-- ok this is stable
这不能满足您的要求,但我想用另一种方式来说明。
事实上,我已经实现了对元组列表进行排序的经典规则。
现在我将尝试定义您的“排序”,然后我将为MPair重新定义Ord实例。这样,

instance (Ord a, Num a) => Ord (MPair a) where  
    compare p@(MPair a b) q@(MPair c d) 
            | p == q        = EQ 
            | check a b c d = LT  
            | otherwise     = GT 
                where 
                  pred x y = (abs (x - y)) < 2
                  check a b c d = pred a c && pred b d
我意识到您的订单的稳定性并不令人满意,那么排序就不是您所需要的

最后,我想说这没有意义,因为您没有在元组列表上定义顺序。您的标准是一个判别式,它允许您创建两个子组数据。([标准x为真],[标准x为假])。像往常一样对元组列表进行排序,并定义一个指定函数(基于您的条件),该函数将创建两个不同的组


PS:也许你可以使用基于你的标准的函数在你的数据上建立一个订单,但我不知道如何实现它

我不明白你所说的“y'和x'之间0或1的差异应该是主要的”是什么意思。是的,我也不明白。你能解释一下为什么(2,1)应该在(0,3)之前吗?不确定你所描述的可以表示为一种排序,因为你不是简单地比较
(2,1)
(0,3)
本身,而是在另一个值
(2,0)
的上下文中。例如,给定
[(0,0),(0,1),(0,2)]
,则该和
[(0,2),(0,1),(0,0)]
都是有效的。如果我误解了您的描述,请详细说明。我投票决定结束:groovy的两个(或三个,请看Charles D的答案)示例无法解释他想要什么,试图猜测可能的成对顺序是浪费每个人的时间。您的意图非常不清楚。不过我可以推荐一个策略。首先,定义从成对到表示顺序的结果类型的转换函数,例如算术运算的数值结果。第二,使用此函数对数据进行排序。我得到了这个
[(4,2),(4,1),(2,3),(1,3),(2,1),(0,3),(2,0),(1,1),(0,1)]
我做错什么了吗?我想我只是倒着写的,试着在subsortGT中交换LT和GT?我现在正在安装GHC lol.ok…
[(4,2),(2,3),(4,1),(1,3),(0,3),(2,1),(1,1),(2,0),(0,1)]
我以为我认出了你的名字,哈哈……我这么做的原因是为了回答你问过的同一个问题:我的想法是只列出1的坐标,然后排序(就像我尝试做的那样)然后简单地按照相同的原则将它们分组
(diff x-x'和y-y'小于2)
,以获得对象的数量!哦,好了,现在我知道你想做什么了,这不是一个很好的排序操作。我会看看我是不是搞不懂什么,我很开心。谢谢你的思考——我发布的例子确实有用,但对于这一个
[(0,1)、(0,3)、(1,1)、(1,3)、(2,1)、(2,1)、(2,3)、(4,1)、(4,1)、(4,2)]
它输出
[(0,1)、(1,1)、(2,1)、(0,3)、(2,2)、(1)、(1,3)、(4,1)、(4,2)]
,在我更喜欢的地方,(2,3)、(1,3)、(0,3)、(4,1)、(4,2)]
>>> fromMPairToList $ sort $ fromListToMPair testList
[(0,1),(0,3),(1,1),(1,3),(2,0),(2,1),(2,3),(4,1),(4,2)]
-- add a test to check the stability of your order.  
>>> fromMPairToList $ sort $ sort $ fromListToMPair testList 
[(0,1),(0,3),(1,1),(1,3),(2,0),(2,1),(2,3),(4,1),(4,2)]
-- ok this is stable
instance (Ord a, Num a) => Ord (MPair a) where  
    compare p@(MPair a b) q@(MPair c d) 
            | p == q        = EQ 
            | check a b c d = LT  
            | otherwise     = GT 
                where 
                  pred x y = (abs (x - y)) < 2
                  check a b c d = pred a c && pred b d
>>> fromMPairToList $ sort $ fromListToMPair testList
[(4,1),(4,2),(2,3),(2,0),(2,1),(1,3),(1,1),(0,3),(0,1)]
>>> fromMPairToList $ sort $ sort $ fromListToMPair testList
[(0,1),(0,3),(2,0),(1,1),(2,3),(1,3),(2,1),(4,1),(4,2)]
-- no this won't work, this is not an ordering, you cannot sort.