9
$\begingroup$

Given some number nand set of values vals, I want to obtain all the tuples/permutations of size n for the values in vals, but without any repeated tuples. So e.g. n=2 and vals={3,6} should give

 n = 2, vals = {0,1}   --> { {0,0}, {0,1}, {1,1} }
 n = 2, vals = {0,1,2} --> { {0,0}, {0,1}, {0,2}, {1,1}, {1,2}, {2,2} }
 n = 3, vals = {0,1}   --> { {0,0,0}, {0,0,1}, {0,1,1}, {1,1,1} }
 n = 3, vals = {0,1,2} --> { {0,0,0}, {0,0,1}, {0,0,2}, {0,1,1}, {0,1,2}, {0,2,2}, {1,1,1}, {1,1,2}, {1,2,2}, {2,2,2} }

I've tried the following commands:

 n    = 2;
 vals = {0, 1};
 Tuples[vals, {n}]        (* gives { {0, 0}, {0, 1}, {1, 0}, {1, 1} } *)
 Permutations[vals, {n}]  (* gives { {0, 1}, {1, 0} } *)
 Subsets[vals, {n}]       (* gives { {0, 1} } *)

Permutations and Subsets are incomplete. Tuples contains all the right combinations, but also contains duplicates like {0, 1} and {1, 0}. Since I do not care about order, I'd like to remove those.

How do I achieve the behavior of Tuples, but without duplicates?

$\endgroup$
1

2 Answers 2

6
$\begingroup$
n = 2;
vals = {0, 1};
Tuples[vals, {n}] // DeleteDuplicatesBy[#, Sort] &

As the comment said

Tuples[vals, {n}] // DeleteDuplicatesBy[Sort]

Also works, more clear.

Some explanations:

The key is: you "sort" the list to see whether they are duplicate.

So I use Sort to be DeleteDuplicatesBy's condition.

$\endgroup$
4
  • $\begingroup$ Perfect. Just curious, how does this syntax work? $\endgroup$
    – Phil-ZXX
    Commented Aug 18, 2020 at 12:39
  • $\begingroup$ @Phil-ZXX I add some explanations. $\endgroup$ Commented Aug 18, 2020 at 12:43
  • $\begingroup$ @Phil-ZXX if you mean: this syntax, then a//f[#,b]& == f[a,b] , but sometimes a is too long to put in a [] .So I use this way to put it out. $\endgroup$ Commented Aug 18, 2020 at 12:46
  • 2
    $\begingroup$ Note that DeleteDuplicatesBy has an operator form, so … // DeleteDuplicatesBy[Sort] will also work $\endgroup$
    – Lukas Lang
    Commented Aug 18, 2020 at 21:13
11
$\begingroup$

The accepted answer will quickly blow up with arguments of more than trivial sizes.

For example, with vals = {10, 20, 5, a, b, c} and n=10, it takes nearly two minutes to finish on my laptop, generating only 3003 results.

Better to generate the results directly, as a simple nested iteration:

f2[vals_, n_] := 
 With[{i = {#2, #1, Length@vals} & @@@ 
     Partition[Prepend[Array[i, n], 1], 2, 1]}, 
  Partition[vals[[Flatten[Table @@ {i[[All, 1]], Sequence @@ i}]]], n]];

This takes a few hundredths of a second to generate the same results from the aforementioned example.

It will also handle cases where the current answer will simply crash out with a "insufficient memory available" error (say 20 values and length 10).

$\endgroup$

Not the answer you're looking for? Browse other questions tagged or ask your own question.