如何将此mergeWords函数扩展为任意数量的字符串?

时间:2017-07-07 11:14:16

标签: haskell functional-programming purely-functional

以下是mergeWords函数。

mergeWords [] [] = []
mergeWords [] (y:ys) = y:'\n':(mergeWords [] ys)
mergeWords (x:xs) [] = x:'\n':(mergeWords xs [])
mergeWords (x:xs) (y:ys) = x:y:'\n':(mergeWords xs ys)

如果应用于mergeWords "hello" "world",则会提供

"hw\neo\nlr\nll\nod\n"

我无法弄清楚如何将其扩展到字符串列表。就像将它应用于3个字符串时,首先应该先取每个字符串的第一个字符然后再加上'\ n'然后再加上第二个字​​符,依此类推。

2 个答案:

答案 0 :(得分:4)

这个难题实际上是将单词的列表(一次一个字符)合并为带有尾随换行符的行。

mergeWords :: [String] -> String

我们需要列出像

这样的列表
[ "hello"
, "jim"
, "nice"
, "day"
]

并将其重新排列到给定位置的事物列表中

[ "hjnd"
, "eiia"
, "lmcy"
, "le"
, "o"
]

库函数transpose的功能。

然后我们需要创建一个字符串,将其视为行,由换行符分隔。这是unlines的作用。

所以

mergeWords = unlines . transpose

我们已经完成了。

答案 1 :(得分:2)

如果你分步进行,听起来相当容易:

cutWords :: [String] -> [[String]]    -- ["ab", "cd", "e"] -> [["a", "c", "e"], ["b", "d"]]
concatWord :: [String] -> String       -- ["a", "c", "e"] -> "ace\n"
concatWords :: [String] -> String    -- use mergeWord on all of them

最有趣的部分当然是cutWords部分。你想要的是一种类似拉链的行为,如果我们安全的话,它会有所帮助。 tailhead

head' (x:xs) = [x]
head' "" = ""

tail' (x:xs) = xs
tail' "" = ""

现在我们可以实施cutWords,确保我们及时停止:

cutWords xs = heads : rest
  where
    heads = map head' xs
    tails = map tail' xs
    rest = if any (/= "") tails then cutWords tails
                                else []

然后剩下的部分是微不足道的:

concatWord word = concat word ++ "\n"
concatWords words = concatMap concatWord word