连接 returns 多于应有的元素

Сoncatenation returns more elements than it should

我需要在 1D 封闭域上获取细胞的邻居

例如:

邻居[1,2,3,4,5,-1](6个元素)

必须 return [[-1,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5, -1],[5,-1,1]](6个元素)

我的邻居代码

neighbours :: [a] -> [[a]]
neighbours l = concat [[[last l, head l, last $ take 2 l]], neighbours' l, [[l !! (length l - 2), last l, head l]]] where
    neighbours' :: [a] -> [[a]]
    neighbours' (a:b:c:xs) = [a, b, c]:neighbours (b:c:xs)
    neighbours' _ = []

main = print $ neighbours [1, 2, 3, 4]

returns [[4,1,2],[1,2,3],[4,2,3],[2,3,4],[4,3,4 ],[3,4,3],[3,4,2],[3,4,1]](8 个元素),但应为 [[4,1,2],[1,2,3], [2,3,4],[3,4,1]](4 个元素)

如果我评论邻居'l它return [[4,1,2],[3,4,1]] 符合预期(2 个元素)

如果你只留下邻居的l它return [[1,2,3],[2,3,4]] 符合预期(2 个元素)

2+2=4,但在这种情况下由于某种原因它是 8

为什么会这样?

P.s.

邻居的创建列表中间

邻居的 [1,2,3,4,5,-1] == [[1,2,3],[2,3,4],[3,4,5],[4 ,5,-1]]

[last l, head l, last $ take 2 l] 创建列表的头部 [-1,1,2]

[l !! (length l - 2), last l, head l] 创建列表 [5,-1,1]

的最后一个元素

您的代码有点难以理解,因为您的两个函数 neighbourneighbour' 相互 递归的,这有点不寻常。

代码中的关键行是:

neighbours' (a:b:c:xs) = [a, b, c] : neighbours (b:c:xs)

如果我们假设这不是故意的,而您只是想写:

neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
-----------------------------------------------+---------

那么代码就如你所料的那样工作了。

请注意,代码行较长(超过 80 个字符)会使调试变得非常困难。

建议代码:

{-#  LANGUAGE  ScopedTypeVariables  #-}
{-#  LANGUAGE  ExplicitForAll       #-}

import qualified  Data.List  as  L

neighbours :: [a] -> [[a]]
neighbours l = concat [
                         [[last l, head l, last $ take 2 l]],
                         neighbours' l,
                         [[l !! (length l - 2), last l, head l]]
                      ]
  where
    neighbours' :: [a] -> [[a]]
    neighbours' (a:b:c:xs) = [a, b, c] : neighbours' (b:c:xs)
    neighbours' _ = []


-- neighbour is British English, neighbor is US English
neighbors :: [a] -> [[a]]
neighbors xs =
    take count $ drop  (count-1)  allTriplets  -- section of infinite list
      where
        count        =  length xs
        allTriplets  =  map  (take 3)  (L.tails (cycle xs))  -- raw material


main :: IO ()
main = do
    print $ "res1 = " ++ (show $ neighbours [1, 2, 3, 4])
    print $ "res2 = " ++ (show $ neighbors  [1, 2, 3, 4])

程序输出:

"res1 = [[4,1,2],[1,2,3],[2,3,4],[3,4,1]]"
"res2 = [[4,1,2],[1,2,3],[2,3,4],[3,4,1]]"