List 查找两个列表的所有可能交点

List 查找两个列表的所有可能交点,list,haskell,intersection,List,Haskell,Intersection,假设我有一个列表[2,4,1,5,4]和一个列表[2,4,5,1],那么我希望有一个intersect函数,它将给出所有可能的交点。因此,在这种情况下,函数将输出[[2,4,1,5]、[2,1,5,4]]的列表 内置的intersect将给我[4,2,1,5,4] 我试着从做一个函数开始 intersect'xs ys=xs\\(xs\\ys) 这只给了我一个可能性-[2,1,5,4] 我将非常感谢您的帮助 内置的intersect将给我[4,2,1,5,4] 从[4,2,1,5,4]中,您可以

假设我有一个列表[2,4,1,5,4]和一个列表[2,4,5,1],那么我希望有一个intersect函数,它将给出所有可能的交点。因此,在这种情况下,函数将输出[[2,4,1,5]、[2,1,5,4]]的列表

内置的intersect将给我[4,2,1,5,4]

我试着从做一个函数开始

intersect'xs ys=xs\\(xs\\ys)

这只给了我一个可能性-[2,1,5,4]

我将非常感谢您的帮助

内置的intersect将给我[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 :: Eq a => [a] -> [a] -> [[a]]
intersections xs ys = uniqs (intersect xs ys)

由于您使用的第二个列表类似于多个集合,因此让我们在类型中明确这一点:

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

你需要所有可能的交叉点。所以我认为你可以生成你的交点的幂集。您可以使用Guava-@Razib,Guava不是Java库吗?对不起,什么是Guava?hques12,如果我没有弄错的话,这完全不相关。你能更好地解释一下“所有可能的交叉点”是什么意思吗?因此,如果我有一个顺序重要的列表1,这里是[2,4,1,5,4],还有一个可以是任何顺序的列表2[2,4,5,1],那么我希望有一个函数来生成列表1的子序列,其中包含列表2中的所有元素。但是,如果一个元素在列表1中出现两次,那么它需要在列表2中出现两次才能包含两次。请注意,这将是二次的,因为我们使用
elem
重复进行线性搜索。