如何将列表[1,2,4,1,5,7,3,4,2,3]划分为一个子列表列表,这些子列表将按断开序列的值进行拆分。例如,列表[1,2,4,1,5,7,3,4,2,3]应该产生一个子列表,如[[1,2,4],[1,5,7],[ 3,4],[2,3]。
有关此问题的任何想法或建议如何解决此问题?
感谢。
答案 0 :(得分:9)
就像上面的Travis一样,我的第一个想法就是用自己的尾巴压缩列表: 但是,在这种情况下它看起来不太合适。不仅没有真正的分割功能完全符合您的要求,而且还存在一个问题,即您将在开头或结尾丢失一个元素。代替正确抽象的解决方案,请看一下:
splitAscending :: Ord a => [a] -> [[a]]
splitAscending = foldr f [] where
f x [] = [[x]]
f x (y:ys) = if x < head y
-- It's okay to call head here because the list y is
-- coming from the summary value of the fold, which is [[a]].
-- While the sum value may be empty itself (above case), it will
-- never CONTAIN an empty list. In general be VERY CAREFUL when
-- calling head.
then (x:y):ys -- prepend x to the first list in the summary value
else [x]:y:ys -- prepend the new list [x] to the summary value
快速而肮脏的解决方案,我希望它符合您的需求
- 另外,这是我在Stack Overflow上的第一篇文章:)
答案 1 :(得分:4)
这里有一个提示:每当你需要在处理列表时查看连续元素时,最好先将列表压缩到尾部:
Prelude> let f xs = zip xs $ tail xs
Prelude> f [1,2,4,1,5,7,3,4,2,3]
[(1,2),(2,4),(4,1),(1,5),(5,7),(7,3),(3,4),(4,2),(2,3)]
现在,您可以使用splitWhen $ uncurry (>)
(splitWhen
来自Data.List.Split
)的内容来适当地划分列表。
答案 2 :(得分:2)
你可以用2个函数来做,一个在第一个项低于第二个项时分割头,另一个用函数输出分割头的函数,并将递归调用的结果连接到自身列表的尾部。
splitList :: [Int] -> [[Int]]
splitList [] = []
splitList (x:xs) = ys : splitList zs
where (ys,zs) = splitHead (x:xs)
splitHead :: [Int] -> ([Int], [Int])
splitHead [x] = ([x], [])
splitHead (x:y:xs)
| x > y = ([x], (y:xs))
| x <= y = (x:ys, zs)
where (ys,zs) = splitHead (y:xs)
答案 3 :(得分:2)
嗯,这并不像我希望的那样干净,但现在就是这样。 使用包拆分:http://hackage.haskell.org/package/split
:m+ Data.List.Split
Prelude Data.List.Split> let f ys = let ys' = zip ys (tail ys) in map (map fst) ((split . whenElt) (uncurry (>)) $ ys')
这里很可能会清理牙箍。
答案 4 :(得分:1)
怎么样
asc [] = [[]]
asc (x:xs) = map reverse $ reverse $ foldl ins [[x]] xs
where ins ((y:ys):yss) z | z > y = (z:y:ys) : yss
| otherwise = [z] : (y:ys) : yss
或
asc = map reverse.reverse.foldl ins [[]]
where ins [[]] z = [[z]]
ins ((y:ys):yss) z | z > y = (z:y:ys) : yss
| otherwise = [z] : (y:ys) : yss