![](/img/trans.png)
[英]Flatten nested list of lists with variable numbers of elements to a data frame
[英]Is there a function to flatten a nested list of elements?
如何拼合這樣的嵌套列表:
[1, 2, 3, 4] == flatten [[[1,2],[3]],[[4]]]
是的,它是concat
從標准前奏, 由下式給出
concat :: [[a]] -> [a]
concat xss = foldr (++) [] xss
如果要將[[[a]]]
變成[a]
,則必須使用它兩次:
Prelude> (concat . concat) [[[1,2],[3]],[[4]]]
[1,2,3,4]
由於沒有其他人給出這個,因此可以定義一個函數,該函數將使用MultiParamTypeClasses展平任意深度的列表。 我實際上並沒有發現它有用,但希望它可以被認為是一個有趣的黑客。 我從Oleg的多變量函數實現中得到了這個想法。
{-# LANGUAGE MultiParamTypeClasses, OverlappingInstances, FlexibleInstances #-}
module Flatten where
class Flatten i o where
flatten :: [i] -> [o]
instance Flatten a a where
flatten = id
instance Flatten i o => Flatten [i] o where
flatten = concatMap flatten
現在,如果你加載它並在ghci中運行:
*Flatten> let g = [1..5]
*Flatten> flatten g :: [Integer]
[1,2,3,4,5]
*Flatten> let h = [[1,2,3],[4,5]]
*Flatten> flatten h :: [Integer]
[1,2,3,4,5]
*Flatten> let i = [[[1,2],[3]],[],[[4,5],[6]]]
*Flatten> :t i
i :: [[[Integer]]]
*Flatten> flatten i :: [Integer]
[1,2,3,4,5,6]
請注意,通常需要提供結果類型注釋,否則ghc無法確定在何處停止遞歸應用flatten
類方法。 如果你使用的單態類型的函數就足夠了。
*Flatten> :t sum
sum :: Num a => [a] -> a
*Flatten> sum $ flatten g
<interactive>:1:7:
No instance for (Flatten Integer a0)
arising from a use of `flatten'
Possible fix: add an instance declaration for (Flatten Integer a0)
In the second argument of `($)', namely `flatten g'
In the expression: sum $ flatten g
In an equation for `it': it = sum $ flatten g
*Flatten> let sumInt = sum :: [Integer] -> Integer
*Flatten> sumInt $ flatten g
15
*Flatten> sumInt $ flatten h
15
正如其他人所指出的那樣, concat :: [[a]] -> [a]
是你正在尋找的函數,它不能展平任意深度的嵌套列表。 您需要多次調用它以將其展平至所需級別。
不過,該操作確實可以推廣到其他monad。 然后它被稱為join
,並且具有Monad m => m (ma) -> ma
。
Prelude Control.Monad> join [[1, 2], [3, 4]]
[1,2,3,4]
Prelude Control.Monad> join (Just (Just 3))
Just 3
Prelude Control.Monad.Reader> join (+) 21
42
import Data.List
let flatten = intercalate []
flatten $ flatten [[[1,2],[3]],[[4]]]
[1,2,3,4]
正如哈馬爾指出的那樣, join
是壓縮名單的“monadic”方式。 您也可以使用do
-otation來輕松編寫幾個級別的平面函數:
flatten xsss = do xss <- xsss
xs <- xss
x <- xs
return x
任意嵌套的列表可以通過Data.Tree
來近似,可以通過適當命名的函數flatten
。
我說近似因為Data.Tree
允許將數據項附加到每個節點,而不僅僅是葉子。 但是,您可以創建一個Data.Tree (Maybe a)
,並將Nothing
附加到body節點,並使用catMaybes . flatten
展平catMaybes . flatten
catMaybes . flatten
。
您可以使用concat
刪除一級嵌套,因此可以通過應用concat
n次來應用n級嵌套。
這是不可能的(使用列表數據類型寫入一個函數,它消除嵌套的任意水平,因為它不能夠表達一個函數,該函數的任意嵌套列表並返回一個平坦的列表,使用Haskell的類型系統的類型也就是說 - 你可以為任意嵌套的列表編寫自己的數據類型,並為此編寫一個flatten函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.