Haskell:: 如何在列表之间比较/提取/添加每个元素



我正在尝试从列表列表中获取每个元素。

例如,[1,2,3,4] [1,2,3,4]

我需要创建一个列表,它是 [1+1, 2+2, 3+3, 4+4]

列表可以是任何东西。"abcd" "defg" => ["ad","be","cf","dg"]

问题是两个列表可以有不同的长度,所以我不能使用 zip。

这是一回事,另一回事是比较。

我需要将 [1,2,3,4] 与 [1,2,3,4,5,6,7,8] 进行比较。第一个列表可以比第二个列表长,第二个列表可能比第一个列表长。

因此,如果我将 [1,2,3,4] 与 [1,2,3,4,5,6,7,8] 进行比较,结果应该是 [5,6,7,8]。无论第一个列表没有什么,但第二个列表有,都需要输出。

我也不能使用任何递归函数。我只能导入数据字符

问题是两个列表可以有不同的长度,所以我不能使用 zip。

在这种情况下,结果应该是什么?

不能使用任何递归函数

那就不可能了。某会有递归,要么在你使用的库函数中(如在其他答案中),要么在你自己编写的函数中。我怀疑你误解了你的任务。

对于您的第一个问题,您可以使用zipWith:

zipWith f [a1, a2, ...] [b1, b2, ...] == [f a1 b1, f a2 b2, ...]
就像

,就像你的例子一样,

Prelude> zipWith (+) [1 .. 4] [1 .. 4]
[2,4,6,8]
我不确定在列表长度

不同的情况下你需要什么。标准zipzipWith只是忽略没有对的较长元素。你可以让它们保持不变,并编写你自己的zipWith模拟,但它会像zipWithRest :: (a -> a -> a) -> [a] -> [a] -> [a]这样的东西,这与第二个带有字符串的示例的类型相矛盾。

对于第二个,您可以使用列表推导式:

Prelude> [e | e <- [1 .. 8], e `notElem` [1 .. 4]]
[5,6,7,8]

不过,它会很慢

对于您的第二个问题(如果我没看错的话),一个简单的过滤器或列表理解就足够了:

uniques a b = filter (not . flip elem a) b
我相信

您可以使用 concat 和 nub http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-List.html#v%3anub 的组合来解决这个问题,这将删除所有重复项......

nub (concat [[0,1,2,3], [1,2,3,4]])

在执行此操作之前,您需要从第一个列表中删除唯一元素。 即 0(使用相同的函数)

填充

然后压缩

您在评论中建议了以下示例:

[1,2,3,4] [1,2,3] => [1+1, 2+2, 3+3, 4+0] 
"abcd" "abc" => ["aa","bb","cc"," d"]

我们可以通过用默认值填充列表来解决这些类型的问题:

padZipWith :: a -> (a -> a -> b) -> [a] -> [a] -> [b]
padZipWith def op xs ys = zipWith op xs' ys' where
     maxlen = max (length xs) (length ys)
     xs' = take maxlen (xs ++ repeat def)
     ys' = take maxlen (ys ++ repeat def)

所以例如:

ghci> padZipWith 0 (+) [4,3] [10,100,1000,10000]
[14,103,1000,10000]
ghci> padZipWith ' ' (x y -> [x,y]) "Hi" "Hello"
["HH","ie"," l"," l"," o"]

(您可以重写padZipWith有两个单独的默认值,每个列表一个,这样您就可以允许两个列表具有不同的类型,但这听起来不是很有用。

一般超出共同长度

对于您关于超出常见长度的压缩的第一个问题:

如何使用 Data.List 中的splitAt :: Int -> [a] -> ([a], [a])将您的列表拆分为两个都有的初始段和一个只有一个的尾巴:

bits xs ys = (frontxs,frontys,backxs,backys) where
      (frontxs,backxs) = splitAt (length ys) xs
      (frontys,backys) = splitAt (length xs) ys

例:

ghci> bits "Hello Mum" "Hi everyone else"
("Hello Mum","Hi everyo","","ne else")

您可以通过多种方式使用它:

larger xs ys = let (frontxs,frontys,backxs,backys) = bits xs ys in
       zipWith (x y -> if x > y then x else y) frontxs frontys ++ backxs ++ backys
needlesslyComplicatedCmpLen xs ys = let (_,_,backxs,backys) = bits xs ys in
       if null backxs && null backys then EQ
         else if null backxs then LT else GT
-- better written as   compare (length xs) (length ys)

所以

ghci> larger "Hello Mum" "Hi everyone else"
"Hillveryone else"
ghci> needlesslyComplicatedCmpLen "Hello Mum" "Hi everyone else"
LT

但是一旦你掌握了splitAttaketakeWhiledrop等的窍门,我怀疑你是否需要编写像bits这样的辅助函数。

最新更新