如何在mathematica中返回包含重复项的两个列表的交集?

时间:2017-09-10 19:03:43

标签: math wolfram-mathematica

如何在mathematica中找到包含重复项的两个列表的交集?

所以,如果我有这个:

list1 = {1, 1, 3, 4, 5, 6, 6, 6, 7, 7, 10, 11, 11};
list2 = {1, 1, 4, 5, 5, 6, 6, 7, 7, 8, 11, 11, 13, 14};

我希望它能归还:

IntersectionIncludingDuplicates[list1, list2] = {1, 1, 4, 5, 6, 6, 7, 7, 11, 11}

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

这是一种方式:

Catenate@KeyValueMap[ConstantArray]@
  MapThread[Min, KeyIntersection[Counts /@ {list1, list2}]]

打破它:

  • 计算每个元素在每个列表中出现的次数(Counts
  • 仅保留两个(KeyIntersection
  • 中出现的元素
  • 获取较少次数(MapThreadMin)并多次复制给定元素(ConstantArray

答案 1 :(得分:0)

编辑:修复并测试..

您可以使用常规Intersection,然后使用Count,例如

ConstantArray[#, Min[Count[list1, #], Count[list2, #]]] & /@ 
  Intersection[list1, list2] // Flatten
  

{1,1,4,5,6,6,7,7,11,11}

以函数形式推广以采用任意数量的列表:

IntersectionIncludingDuplicates[lists__List] := 
 ConstantArray[#, 
     Function[{v}, Min @@ (Count[#, v] & /@ {lists})]@#] & /@
   Intersection[lists] // Flatten
IntersectionIncludingDuplicates[list1, list2]
  
    

{1,1,4,5,6,6,7,7,11,11}

  

答案 2 :(得分:0)

简单的代码来理解。假设输入列表已排序。

list1 = {1, 1, 3, 4, 5, 6, 6, 6, 7, 7, 10, 11, 11};
list2 = {1, 1, 4, 5, 5, 6, 6, 7, 7, 8, 11, 11, 13, 14};

IntersectionIncludingDuplicates[list1_, list2_] := Module[

  {out = {}, i = j = 1},

  While[i <= Length[list1] && j <= Length[list2],
   If[list1[[i]] == list2[[j]],
    AppendTo[out, list1[[i]]];
    i++; j++,
    If[list1[[i]] < list2[[j]], i++, j++]]];

  out]

IntersectionIncludingDuplicates[list1, list2]
  

{1,1,4,5,6,6,7,7,11,11}