我正在尝试从列表列表中获取每个元素。
例如,[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]
我不确定在列表长度不同的情况下你需要什么。标准zip
和zipWith
只是忽略没有对的较长元素。你可以让它们保持不变,并编写你自己的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
但是一旦你掌握了splitAt
、take
、takeWhile
、drop
等的窍门,我怀疑你是否需要编写像bits
这样的辅助函数。