我一直试图找到这个问题的解决方案,现在已经有几天了,在我对自己太沮丧之前,我决定寻求帮助。
我有一份统一名单清单,例如: [[2], [2, 2], [3], [3, 3] [3, 3, 3], [5]]
我希望应用过滤器,以便只保留不属于任何其他列表子集的列表。
f
f [[2], [2, 2], [3], [3, 3] [3, 3, 3], [5]]
结果
[[2, 2], [3, 3, 3], [5]]
我希望我已经清楚了。如果没有,请帮我澄清一下!
答案 0 :(得分:2)
假设您的列表都是统一的,因为没有列表包含两个不同的元素(即[2, 3]
),您可以用长度来表示这个问题:
> import Control.Arrow
> -- Equivalent to `\x -> (head x, length x)`
> :t head &&& length
head &&& length :: [a] -> (a, Int)
> (head &&& length) [2, 2, 2]
(2, 3)
>
> let myData = <what you have above>
> map (head &&& length) myData
[(2, 1), (2, 2), (3, 1), (3, 3), (5, 1)]
现在您可以按第一个元素分组
> import Data.List
> :t groupBy
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
> import Data.Function
> :t on
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
> :t on (==) fst
on (==) fst :: Eq b => (b, b1) -> (b, b1) -> Bool
> :t groupBy (on (==) fst)
groupBy (on (==) fst) :: Eq b -> [(b, b1)] -> [[(b, b1)]]
> groupBy (on (==) fst) $ map (head &&& length) myData
[[(2,1),(2,2)],[(3,1),(3,2),(3,3)],[(5,1)]]
然后,您可以选择最大snd
的字词:
> :t maximumBy
maximumBy :: (a -> a -> Ordering) -> [a] -> a
> import Data.Ord
> :t comparing
comparing :: Ord a => (b -> a) -> b -> b -> Ordering
> :t comparing snd
comparing snd :: Ord a => (a1, a) -> (a1, a) -> Ordering
> :t maximumBy (comparing snd)
maximumBy (comparing snd) :: Ord a -> [(a1, a)] -> (a1, a)
> :t map (maximumBy (comparing snd))
map (maximumBy (comparing snd)) :: Ord a => [[(a1, a)]] -> [(a1, a)]
> map (maximumBy (comparing snd)) $ groupBy (on (==) fst) $ map (head &&& length) myData
[(2, 2), (3, 3), (5, 1)]
现在,如果您愿意,可以使用replicate
将其转换回列表:
> map (uncurry (flip replicate)) $ map (maximumBy (comparing snd)) $ groupBy (on (==) fst) $ map (head &&& length) myData
[[2, 2], [3, 3, 3], [5]]
最终功能看起来像
import Data.List (groupBy, maximumBy)
import Data.Ord (comparing)
import Data.Function (on)
import Control.Arrow ((&&&))
biggestUnique :: [[Int]] -> [[Int]]
biggestUnique
= map (uncurry (flip replicate)) -- Convert back to lists
. map (maximumBy (comparing snd)) -- Select by the maximum length
. groupBy ((==) `on` fst) -- Group by the element value
. map (head &&& length) -- Reformulate in terms of length
你可以将map
压缩成一个,但我认为这会降低它的可读性。
警告:如果元素在每个子列表中不唯一,则无法正常工作。
答案 1 :(得分:2)
看起来你想要这个:
import Data.List
import Data.Function
f :: (Ord a) => [[a]] -> [[a]]
f = map (maximumBy (compare `on` length)) . groupBy ((==) `on` head) . sortBy (compare `on` head)
我们只是将列表按其头部分组并选择每个列表的最大值。
如果我不理解你错了,你想要选择不是其他列表的子列表的列表,这实际上是每个组的最长列表。
答案 2 :(得分:1)
没有列表是空列表的正确子列表。空列表是每个非空列表的正确子列表。
import Data.List (delete)
sublist :: Eq a => [a] -> [a] -> Bool
sublist _ [] = False
sublist [] _ = True
sublist (x : xs) ys | x `elem` ys = sublist xs (delete x ys)
| otherwise = False
使用none pred = not . any pred
,但没有Ord
约束:
superlists :: Eq a => [[a]] -> [[a]]
superlists xss = filter (\ xs -> none (xs `sublist`) xss) xss
含义
superlists [[1,2,2],[2,2,1],[1],[]] == [[1,2,2],[2,2,1]]
和
superlists [[2],[2,2],[3],[3,3],[3,3,3],[5]] == [[2,2],[3,3,3],[5]]
具有内容相当的替代sublist
:
elemDelete :: Eq a => a -> [a] -> (Bool, [a])
elemDelete _ [] = (False, [])
elemDelete y (x : xs) | x == y = (True, xs)
| otherwise = let (b, zs) = elemDelete y xs
in (b, x : zs)
sublist :: Eq a => [a] -> [a] -> Bool
sublist _ [] = False
sublist [] _ = True
sublist (x : xs) ys = let (b, dys) = elemDelete x ys
in if b then sublist xs dys
else False
但elemDelete y xs
实际上效率低于(elem y xs, delete y xs)
。