【问题标题】:Concatenate (++) lists without overlap连接 (++) 列表而不重叠
【发布时间】:2017-01-14 13:07:53
【问题描述】:

假设我有两个列表:

l1 = "Hey there"
l2 = "there is a turtle"

如何“连接”列表,但删除与第一个列表结尾匹配的第二个列表的开头?

magic l1 l2 == "Hey there is a turtle"

更多示例,

magic "What's going on" "ing on in the world" == "What's going on in the world"
magic [1,2,3,2] [2,3,2,1] == [1,2,3,2,1]
magic [1..10] [5..20] == [1..20]
magic [1,2] [1,2] == []

我正在寻找的是将列表连接起来然后删除部分 - 仅在“关节” - 列表匹配的地方。


我看过的东西:

  • ++ 只是连接,所以不是我想要的。
  • Data.List\\ 列表差异运算符从第一个列表的前面开始,无论它在哪里,都会从第二个列表中删除它,所以不会起作用。
  • 我不知道我是否可以为此使用stripPrefix,也许它是可行的,但我对haskell的理解还不够好。

我还查看了the entire Data.List 模块,但找不到任何可以开箱即用的东西。

因此看起来有必要创建我们自己的函数来执行此操作,在这种情况下,Prelude 函数解决方案比具有依赖关系的解决方案更可取。

【问题讨论】:

  • 我不认为有一个标准的库函数可以帮助你很多,但你自己编写代码真的不是那么难,至少如果你不介意O (n ²) 复杂度。
  • @leftaroundabout 我不知道该怎么做,我已经尝试了一段时间xD
  • 好吧,天真的方法是尝试所有可能的前缀(第一个列表中的tails),您可能会从第二个列表中删除它们。选择最长的。
  • 我想你可以用一个简单的递归解决方案O(length(l1))来做到这一点:首先看l1是否是l2的前缀,然后tail l1是否是l2的前缀, 那么tail (tail l1))l2 的前缀...
  • @mb21 tails 返回列表列表。因此,tails ... 永远不会是l2 的前缀

标签: list haskell concat


【解决方案1】:

这是一个简单的递归解决方案:

magic x y = f x y y
  where f [] y z = y
        f x [] z = x
        f (x:xs) (y:ys) z = x : if x == y then f xs ys z else f xs z z

【讨论】:

    【解决方案2】:

    我找到了一种方法:

    import Data.List
    overlap xs ys = xs ++ (ys \\ (head ((tails xs) `intersect` (inits ys))))
    

    但我觉得它不是很有吸引力,希望有人可以改进它。

    【讨论】:

      【解决方案3】:

      因为还没有人写这个:

      import Data.List (isPrefixOf)
      
      magic xs ys = s' ++ r'
        where
          (s', r') = go xs
          go []    = ([], [])
          go (x:xs)
            | isPrefixOf (x:xs) ys = ([], ys)
            | otherwise            = (x:s, r)
              where
                (s, r) = go xs
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多