说我有一个列表[2,4,1,5,4]和一个列表[2,4,5,1]然后我希望有一个交叉函数,它将给我所有可能的交叉点。因此,在这种情况下,函数将输出[[2,4,1,5],[2,1,5,4]]的列表。
内置的交叉将给我[4,2,1,5,4]。
我试图通过制作一个函数来开始
intersect' xs ys = xs \\ (xs \\ ys)
这只给了我一种可能性 - [2,1,5,4]。
我很感激任何帮助。
答案 0 :(得分:0)
内置的交叉将给我[4,2,1,5,4]。
从[4,2,1,5,4]
开始,您可以使用此功能获取[[2,4,1,5], [2,1,5,4]]
:
uniqs :: Eq a => [a] -> [[a]]
uniqs [] = [[]]
uniqs (x:xs)
| x `elem` xs = map (x:) (uniqs (filter (/= x) xs)) ++ uniqs xs
| otherwise = map (x:) (uniqs xs)
然后您的intersections
只是
intersections :: Eq a => [a] -> [a] -> [[a]]
intersections xs ys = uniqs (intersect xs ys)
答案 1 :(得分:0)
由于您使用的是第二个列表,例如多套装,因此请在类型中明确说明:
intersections :: Ord a => [a] -> MultiSet a -> [[a]]
列表和空多集的唯一交集是空列表
intersections _ m | M.null m = [[]]
没有空列表和非空多集的交叉点
intersections [] _ = []
给定一个非空列表和一个非空多重集,我们有所有使用第一个项目的交叉点,以及所有没有交叉的交叉点
intersections (a:as) m = with ++ without
如果列表中的第一项不在多重集中,那么没有使用它的交叉点
where with = case M.lookup a m of
Nothing -> []
如果它在多组中,那么使用该项目的交叉点只是在删除该项目的一个实例后,列表其余部分和多组交叉点的扩展,
Just n -> map (a:) . intersections as $ update a (n-1) m
不使用该项目的交叉点可以通过递归轻松定义
without = intersections as m
为了完整性,多集的定义:
import qualified Data.Map as M
import qualified Data.List as L
type MultiSet a = M.Map a Int
fromList :: Ord a => [a] -> MultiSet a
fromList = L.foldl' (\m a -> M.insertWith' (+) a 1 m) M.empty
toList :: MultiSet a -> [a]
toList = concatMap (uncurry $ flip replicate) . M.toList
update :: Ord a => a -> Int -> MultiSet a -> MultiSet a
update a 0 = M.delete a
update a n = M.insert a n