簡體   English   中英

Haskell ::如何比較/提取/添加列表之間的每個元素

[英]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]

我不確定列表長度不同時需要什么。 標准zipzipWith僅忽略較長的沒有一對的元素。 您可以將它們保留不變,並編寫自己的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

但是一旦掌握了splitAttaketakeWhiledrop等功能,我懷疑您是否需要編寫輔助函數,例如bits

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM