# Subtracting one list of lists from another

I have two lists of lists, like:

list1 = {{2}, {4}, {3, 1}, {2, 2}, {6}, {5, 1}, {4, 2}, {4, 2}, {8}, {7, 1},
{6, 2}, {6, 2}, {5, 3}, {4, 4}}
list2={{2, 2}, {4, 2}, {6, 2}, {4, 4}}


Note that, in list1, the partitions {4,2} and {6,2} occur twice. In general, there could be more than 2 occurrences of a particular element of either list, and my partitions could have more than 2 parts.

I want to "subtract" the contents of list2 from list1 (i.e. count its occurrences negatively, and merge it with list1) so the final result is

list3= {{2}, {4}, {3, 1}, {6}, {5, 1}, {4, 2}, {8}, {7, 1}, {6, 2},  {5, 3}}


i.e. if a partition $$(a_1,a_2,\ldots,a_k)$$ occurs $$p_1(a)$$ times in list1 and $$q_1(a)$$ times in list2, the result should be a list where $$(a_1,a_2,\ldots,a_k)$$ occurs $$p_1(a)-q_1(a)$$ times.

"Complement" doesn't quite work here as it would eliminate {4,2} and {6,2} from list3. Any help would be appreciated.

For context this come up when using modification rules for non-standard representations, which here are represented by partitions. The modification rules produce partitions with negative coefficient which cancels out'' an appropriate number of like standard representations in some expansion: see for instance

King RC. Modification rules and products of irreducible representations of the unitary, orthogonal, and symplectic groups. Journal of Mathematical Physics. 1971 Aug;12(8):1588-98.

• list3 should not contain {2,2}, right?
– kglr
Commented May 18, 2021 at 19:43
• @kglr fixed. Thanks. Commented May 18, 2021 at 19:46
• you also need to remove {4,4} from list3?
– kglr
Commented May 18, 2021 at 20:01
• @kglr yes as you can see removing manually from a long list is not very convenient... Commented May 18, 2021 at 20:49

## 4 Answers

Fold[DeleteCases[##, 1, 1] &, list1, list2]

{{2}, {4}, {3, 1}, {6}, {5, 1}, {4, 2}, {8}, {7, 1}, {6, 2}, {5, 3}}

Join @@ KeyValueMap[ConstantArray][Subtract @@ KeyUnion[Counts /@ {list1, list2}, 0 &]]

{{2}, {4}, {3, 1}, {6}, {5, 1}, {4, 2}, {8}, {7, 1}, {6, 2}, {5, 3}}


Alternatively,

KeyValueMap[Apply[Sequence]@*ConstantArray][
Subtract @@ KeyUnion[Counts /@ {list1, list2}, 0 &]]

{{2}, {4}, {3, 1}, {6}, {5, 1}, {4, 2}, {8}, {7, 1}, {6, 2}, {5, 3}}

• The second option I understand better and works perfectly. Thanks. Commented May 18, 2021 at 21:04
Delete[list1,FirstPosition[list1, #]&/@list2]


{{2}, {4}, {3, 1}, {6}, {5, 1}, {4, 2}, {8}, {7, 1}, {6, 2}, {5, 3}}

• Nice! This also works very well. Commented May 19, 2021 at 12:47
la =
{{2}, {4}, {3, 1}, {2, 2}, {6}, {5, 1}, {4, 2}, {4, 2}, {8},
{7, 1}, {6, 2}, {6, 2}, {5, 3}, {4, 4}};

lb = {{2, 2}, {4, 2}, {6, 2}, {4, 4}};


Using DeleteElements (new in 13.1)

DeleteElements[la, 1 -> lb]


{{2}, {4}, {3, 1}, {6}, {5, 1}, {4, 2}, {8}, {7, 1}, {6, 2}, {5, 3}}

l1 =
{{2}, {4}, {3, 1}, {2, 2}, {6}, {5, 1}, {4, 2}, {4, 2}, {8},
{7, 1}, {6, 2}, {6, 2}, {5, 3}, {4, 4}};

l2 = {{2, 2}, {4, 2}, {6, 2}, {4, 4}};


Using Tally we can build the following function:

fun[list1_, list2_] := Module[{f1, f2},
f1 = If[Length@# == 1, First @@ #, Thread@#] &;
f2 = Which[ArrayDepth@# == 1, #,
ArrayDepth@# > 1 && #[[2, 1]] == #[[2, 2]], # /. # -> Nothing,
ArrayDepth@# > 1 && #[[2, 1]] > #[[2, 2]],
First@Drop[#[[1]], -Subtract @@ #[[2]]]] &;
Map[f2@*f1]@GatherBy[Join[Tally[list1], Tally[list2]], First]]

fun[l1, l2]


{{2}, {4}, {3, 1}, {6}, {5, 1}, {4, 2}, {8}, {7, 1}, {6, 2}, {5, 3}}