[英]Compare each index of 3 lists and extract the smallest value of the 3, for every element in the 3 lists
[英]Haskell:: how to compare/extract/add each element between lists
我正在嘗試從列表列表中獲取每個元素。
例如[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]。 無論第一個列表沒有什么,但第二個列表有什么,都需要輸出。
我也不能使用任何遞歸功能。 我只能導入Data.Char
問題是兩個列表的長度可以不同,所以我不能使用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]
( ) slow, though. 不過,它會慢 ( )。
我相信您可以結合使用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(使用相同的功能)
對於第二個問題(如果我沒看錯的話),一個簡單的過濾器或列表理解就足夠了:
uniques a b = filter (not . flip elem a) b
您在評論中建議了以下示例:
[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
以具有兩個單獨的默認值,每個列表一個默認值,因此您可以允許兩個列表具有不同的類型,但這聽起來沒有多大用處。)
對於您關於超出普通長度的拉鏈的第一個問題:
如何使用splitAt :: Int -> [a] -> ([a], [a])
將列表分為一個初始段和一個只有一個Data.List
:
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
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.