7
$\begingroup$

I have an ordered list of integers, i.e.:

list = {1,3,5,6,8,10,12,15};

and I want to know if there is a fast way to get a list of the integers that do not appear in this list. The best thing I've come up with is

list2 = Select[Range[Nd], FreeQ[list,#]&];

which for this particular case yields

{2, 4, 7, 9, 11, 13, 14}

but I suspect there is a faster, more efficient way.

$\endgroup$
2
  • 2
    $\begingroup$ If Nd >= Last[list] then list2 = Range[Nd]; list2[[list]] = Nothing; will do $\endgroup$
    – Coolwater
    Commented Nov 16, 2017 at 16:31
  • $\begingroup$ Thanks for the accept but it is a good habit to hold on a day or two to not discourage others. $\endgroup$
    – Kuba
    Commented Nov 16, 2017 at 22:34

4 Answers 4

6
$\begingroup$

This appears to be faster and scales better, depends on sparsity of list I guess:

Complement[Range[Last[#]], #] &@list
$\endgroup$
2
$\begingroup$
list // Pick[Range[Last@#], SparseArray[# -> #], 0] &

{2, 4, 7, 9, 11, 13, 14}

Or:

list // Range[Last@#] /. Thread[# -> Nothing] &

{2, 4, 7, 9, 11, 13, 14}

$\endgroup$
2
$\begingroup$
list = {1, 3, 5, 6, 8, 10, 12, 15};

Using DeleteElements (new in 13.1)

DeleteElements[Range @ Max @ list, list]

{2, 4, 7, 9, 11, 13, 14}

We used Max instead of Last in case list was not sorted.

$\endgroup$
1
  • 1
    $\begingroup$ +1 Or more generally, DeleteElements[Range @@ MinMax[list], list] $\endgroup$
    – Bob Hanlon
    Commented Jun 9 at 1:18
1
$\begingroup$
list = {1, 3, 5, 6, 8, 10, 12, 15};

Using:

Position[ReplacePart[ConstantArray[0, Max[list]], Thread[list -> 1]], 
  0] // Flatten

-> {2, 4, 7, 9, 11, 13, 14}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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