2d数组在Haskell中排序

时间:2013-12-08 21:14:12

标签: arrays sorting haskell

我正在尝试自学Haskell(来自OOP语言)。很难掌握不可变变量的东西。我正在尝试在行专业中对二维数组进行排序。

在java中,例如(伪):

int array[3][3] = **initialize array here

for(i = 0; i<3; i++)
   for(j = 0; j<3; j++)
      if(array[i][j] < current_low)
         current_low = array[i][j]

如何在Haskell中实现同样的东西?如果我创建一个临时数组以在每次迭代后添加低值,我将无法添加它,因为它是不可变的,对吗?另外,Haskell没有循环,对吧?

这是我在Haskell中所知道的一些有用的东西:

main = do
let a = [[10,4],[6,10],[5,2]] --assign random numbers
print (a !! 0 !! 1) --will print a[0][1] in java notation
--How can we loop through the values?

2 个答案:

答案 0 :(得分:2)

首先,您的Java代码对任何内容进行排序。它只找到最小的元素。而且,有一种明显的Haskell解决方案......猜猜看,该函数被称为minimum!让我们看看它的作用:

  

GHCI&GT; :t最小
  minimum :: Ord a =&gt; [a] - &gt;一个

好的,所以它需要一个可以比较的值列表(因此Ord)并输出一个值,即最小值。我们如何将其应用于“2D列表”(嵌套列表)?嗯,基本上我们需要在子列表的所有最小值中的最小值。所以我们首先用最小值列表替换列表列表

allMinima = map minimum a

...然后使用minimum allMinima

写得紧凑:

main :: IO ()
main = do
   let a = [[10,4],[6,10],[5,2]]   -- don't forget the indentation
   print (minimum $ map minimum a)

这就是全部!


确实,“循环通过价值观”是一个非常缺乏功能的概念。我们通常不想谈论需要采取的单个步骤,而是考虑我们想要的结果属性,并让编译器弄清楚如何做它。因此,如果我们不被允许使用预定义的minimum,请按照以下方式进行思考:

  • 如果我们有一个列表并查看单个值...在什么情况下它是正确的结果?好吧,如果它小于所有其他值。其他值中最小的是什么?确切地说,它们中的最小值。

    minimum' :: Ord a => [a] -> a
    minimum' (x:xs)
       | x < minimum' xs  = x
    
  • 如果它不小,那么我们只使用其他值的最小值

    minimum' (x:xs)
       | x < minxs  = x
       | otherwise  = minxs
     where minxs = minimum' xs
    
  • 还有一件事:如果我们通过这种方式递归列表,那么在某些时候将没有第一个元素可以与某些东西进行比较。为了防止这种情况,我们首先需要单个元素列表的特殊情况:

    minimum' :: Ord a => [a] -> a
    minimum' [x] = x      -- obviously smallest, since there's no other element.
    minimum' (x:xs)
       | x < minxs  = x
       | otherwise  = minxs
     where minxs = minimum' xs
    

答案 1 :(得分:1)

好吧,好吧,我会刺伤一下。扎克,这个答案旨在让你思考递归和折叠。递归,折叠和贴图是在功能样式中替换循环的基本方法。试着相信实际上,嵌套循环的问题很少在函数式编程中自然产生。当你真正需要这样做的时候,你经常会输入一个特殊的代码段,称为monad,你可以用命令式的方式进行破坏性写入。 Here's an example。但是,既然你要求帮助打破循环思维,我将专注于答案的那一部分。 @ leftaroundabout的答案也非常好,你在这里填写了minimum的定义。

flatten :: [[a]] -> [a]
flatten [] = []
flatten xs = foldr (++) [] xs

squarize :: Int -> [a] -> [[a]]
squarize _ [] = []
squarize len xs = (take len xs) : (squarize len $ drop len xs)

crappySort :: Ord a => [a] -> [a]
crappySort [] = []
crappySort xs =
    let smallest = minimum xs
        rest = filter (smallest /=) xs
        count = (length xs) - (length rest)
    in
        replicate count smallest ++ crappySort rest

sortByThrees xs = squarize 3 $ crappySort $ flatten xs