2

第二次更新:

我终于按照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)

第二个例子的输出,在“排序”之后:

*Main> f [(0,1),(1,1),(2,1),(2,2),(2,3),(1,3),(0,3),(4,1),(4,2)]
[[(0,1),(1,1),(2,1),(2,2),(2,3),(1,3),(0,3)],[(4,1),(4,2)]]

--更新结束--

我在构思排序功能时遇到了麻烦,希望有人知道如何实现它,或者说是否需要比自定义排序更多的功能。我试过玩弄 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 y'和x 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)]
4

3 回答 3

5

我的 Haskell 非常生锈,但这应该可以

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)]
于 2013-05-02T03:30:33.883 回答
2

利用元组进行排序

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

customSort = sortBy (comparing (\(x,y) -> (x+y, abs (x-y))))

或带箭头无点(少点)

import Control.Arrow ((&&&))

customSort = sortBy (comparing $ uncurry ((uncurry (&&&) .) ((+) &&& ((abs .) . subtract))))
于 2013-05-02T05:48:27.137 回答
1

尝试在其上定义自定义数据类型和指定顺序。
我建议你像这样

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

然后当我重做 ghci 的测试时,

>>> 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.  

我意识到您的订单稳定性不满意,那么排序不是您所需要的。

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

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

于 2013-05-02T14:54:54.370 回答