第二次更新:
我终于遵循了zurgl的建议并编写了something递归遍历和组。感谢所有想要帮助的人!
第一次更新:
我希望它可以是一个排序功能,但不确定,是为了优化随后的分组(最小化组数)。分组收集水平或垂直相邻的元组:
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)]
答案 0 :(得分:3)
我的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)]
答案 1 :(得分: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))))
答案 2 :(得分: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:也许您可以使用基于您的标准的函数为您的数据建立订单,但我不知道如何实现它。