簡體   English   中英

交換Haskell中的列表列表

[英]Interleave List of Lists in Haskell

我想知道如何在Haskell中編寫一個將列表列表交織到單個列表中的函數,例如,如果我有一個函數調用

interleavelists :: [[a]] -> [a]

它應該能夠交錯元素。

例如: [[1,2,3] [4,5,6] [7,8]] --> [1,4,7,2,5,8,3,6]

列表可以是有限的也可以是無限的...我可以使用foldr嗎?

編寫它的最快方法是使用Data.List transpose

import Data.List

interleavelists :: [[a]] -> [a]
interleavelists = concat . transpose

transpose選擇其參數的每個非空列表的第一個元素,將它們放入一個列表中,然后transpose參數元素的tail列表。 concat enating的列表transpose如所期望的結果交織列表。 如果某些元素列表是無限的,它可以工作,但如果列表列表本身具有無限多個元素,那么它當然永遠不會超過head列表。 但無論如何處理這種情況是有問題的。

使用foldr交錯列表並非易事。 假設你有

interleavelists xss = foldr something zero xss

interleavelists []應該產生[] ,所以'是zero值。

interleavelists [xs] = xs

看起來很自然,所以

something xs [] = xs

但如果第二個參數不是[]怎么辦? 然后,你要插入的第一個參數的元素something在不同的距離到第二個參數。 但在哪個距離? 如果所有列表具有相同的長度,則每個列表的距離都是常量,那么您可以將距離作為另一個參數傳遞,

interleavelists = snd . foldr insertAtDistance (0, [])
  where
    insertAtDistance xs (d, ys) = (d+1, helper d xs ys)
    helper _ [] ws = ws
    helper k (b:bs) cs = b : us ++ helper k bs vs
      where
        (us,vs) = splitAt k cs

這不是很漂亮,如果列表不是全部相同的長度將產生可能不是所需的輸出。 但是如果列表都具有相同的長度,那么它就完成了工作。

簡單的遞歸版本:

inter :: [[a]] -> [a]
inter [] = []
inter xs = inter2 (filter (\x -> not (null x)) xs)
   where inter2 xs = map head xs ++ inter (map tail xs)

現在,關於折疊......

在SICP(以及后來的推理方案)的歡樂時代,“標准”(或許是着名的)交錯列表的方式是

infixr 5 ++/

[]     ++/ ys = ys
(x:xs) ++/ ys = x:(ys ++/ xs)

它可以與foldr一起使用,

*Main> foldr (++/) [] [[1,2,3],[4,5,6],[7,8]]
[1,4,2,7,3,5,8,6]

這顯然不會按照你想要的順序產生結果,但是當列表的輸入列表是無限的時候OTOH工作正常。 我認為沒有辦法同時滿足這兩個要求,因為我們無法知道輸入列表是否是無限的。

上面的結果是Daniel的答案中函數insertAtDistance會產生的,如果修改為總是插入距離1而不是d+1

insertAtDistance xs (d, ys) = (1, helper d xs ys)

當用d+1定義時,它產生“平坦”交錯,而foldr (++/) []產生偏斜交錯:

*Main> take 20 $ foldr (++/) [] [cycle[i] | i<-[1..]]
[1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3]

我們可以做你想做的事

testList = [[1,2,3],[4,5,6],[7,8]]

interleave l = foldr' (concat [map (\x -> f x idx) l | idx <- [0..]])  
    where
        f x n = if (length(x)<=n) then Nothing else Just (x !! n)
        foldr' (x:xs) = case x of 
                         Nothing -> []
                         Just a  -> (:) a (foldr' xs)   

交錯[[1,2,3] [4,5,6] [7,8]] => [1,4,7,2,5,8,3,6]

暫無
暫無

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

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