【问题标题】:Compare elements between two lists - Haskell比较两个列表之间的元素 - Haskell
【发布时间】:2016-05-15 19:08:06
【问题描述】:

这可能是一个愚蠢的问题,但我已经被这个问题困扰了几个小时了。我已经制作了一个遗传算法,但认为我可以尝试改进一下。我想制作一个比较两个数字列表并返回一个值的适应度函数。如果两个列表包含相同的数字并且位于相同的“位置”,则函数应返回 + 2。如果列表包含相同但位置错误的数字,则应返回 + 1。

我制作了两个不同的功能,它们都可以完成其中一项任务,但我无法将它们合并到一个功能中。以下是函数:

samePlace _ [] = 0
samePlace [] _ = 0
samePlace (x:xs) (y:ys)
    | x == y = (sP xs ys) + 2
    | otherwise = sP xs (ys)

此函数为每个相同且位于正确位置的数字返回 +2。

notSamePlace [] _ = 0
notSamePlace _ [] = 0
notSamePlace (x:xs) (ys)
    | elem x (ys) = (notSamePlace xs ys) + 1
    | otherwise = (notSamePlace xs ys)

此函数返回 + 1 是第一个列表中的一个数字存在于第二个列表中。

我遇到的问题是,same-place 函数需要拆分两个列表并一次通过一个数字来比较它们,而 not-the-same-place 函数需要保持第二个列表完整没有把它分成头尾。如果有人能指出如何解决这个问题的正确方向,我将不胜感激。

另外,我的想法是这个函数可以缩短在遗传算法中找到解决方案所需的时间。如果我的解决方案是找到字符串“hello world”,我的想法是具有“leolh owdrl”基因的个体应该比看起来像“hFz%l r0M/z”的基因更适合。到目前为止,在我的程序中,第一个基因的适应度值为 1(因为“空格”是与目标字符在同一位置的唯一字符),但第二个基因具有“h”和“空格”,所以它将被赋予 2 的适应度值。这是一个好主意吗?

谢谢!

【问题讨论】:

  • 提示:编写一个函数,它接受两个列表(as,bs) 并返回(c,as',bs'),其中c 是相同位置的字母数,as' 和@ 987654329@ 是 asbs 删除了这些常用字母。
  • 如果您需要编辑距离作为适应度函数:请参阅hackage.haskell.org/package/align 包(披露:我是作者)。
  • 你能明白为什么这里的notSamePlace 函数对于长字符串会很慢吗?你能想出一种使用辅助数据结构来提供帮助的方法吗?提示:您可以在 containers 包中找到两个明智的选择。其中之一更明显适用;另一个实际上更快。
  • "same-place 函数需要拆分两个列表 [..],而 not-the-same-place 函数需要保持第二个列表完整而不将其拆分为 head和尾巴。”提示:您可以使用 as-pattern,例如list@(x:xs),其中list 将为您提供整个列表,x 为头部,xs 为尾部

标签: list haskell recursion


【解决方案1】:

下面的函数使用zip 来索引每个字符,这允许将完整的第二个列表传递给递归调用。

places :: String -> String -> Int
places _ [] = 0
places [] _ = 0
places xs ys = zippedPlaces (zip xs [1..length xs]) (zip ys [1..length ys])

zippedPlaces :: [(Char, Int)] -> [(Char, Int)] -> Int
zippedPlaces [] _ = 0
zippedPlaces (x:xs) ys =
    let match = filter (\(num, i) -> fst x == num) ys
    in case match of
        [] -> zippedPlaces xs ys
        (a:_) -> (if snd a == snd x then 2 else 1) + zippedPlaces xs ys

【讨论】:

  • 感谢 Kapol 的回答!甚至没有考虑到您可以为此使用 zip 功能...有时您只需要一个新的视角来解决问题。再次感谢! :)
  • *Main Data.Map Data.List> places "Hello" "Hel" 7 看起来不太聪明
【解决方案2】:

假设没有列表包含重复项:

place [] _ = 0
place _ [] = 0
place (x:xs) (y:ys) = place xs ys +
  if x == y then 1 else (if elem x ys then 2 else 0) + (if elem y xs then 2 else 0)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 2019-01-17
    • 2016-04-01
    • 2011-02-21
    • 2019-12-07
    相关资源
    最近更新 更多