3
$\begingroup$

What is the inverse of the Position?

I have an array which contains the positions of elements and I want a function which returns an List which contains 1 where those elements are and 0 elsewhere. For example, the List {1, 5} would return {1,0,0,0,1} or {2,1,4} would return {1,1,0,1}. Additional arguments might need to be supplied for length etc. (Technically, this function is a inverse of restricted version of the Position function)

I realize that I could do with Table but it seems like this would be a common enough process that there would be a built in function for this. However, I have not been able to find it in the documentation.

$\endgroup$
  • 3
    $\begingroup$ Am I missing something? Reverse[IntegerDigits[Tr[2^(#-1)],2]]& s/b quite efficient. Add the length argument to IntegerDigits if you want a mask matching some arbitrary length. $\endgroup$ – ciao Sep 4 '17 at 1:26
  • 1
    $\begingroup$ I would not call that the inverse of Position ... the true inverse of Position, i.e. a function that takes Position's output and returns its input, is Extract $\endgroup$ – Szabolcs Sep 5 '17 at 12:34
7
$\begingroup$

I don't know that you can do it in a single command. But it's easy enough to do in two. Say your list is list={2,1,4};

x = ConstantArray[0, Max[list]];
x[[list]] = 1;

x
{1, 1, 0, 1}

Effectively, Part (or the shortcut [[ ]]) acts as an approximate inverse of Position.

$\endgroup$
  • $\begingroup$ Accepting this answer because it is the fastest in my limited testing $\endgroup$ – The Square Cow Sep 5 '17 at 14:00
  • $\begingroup$ @TheSquareCow This solution is silent about duplicates. (Also, it is hard to believe it is fastest. Can you post your tests?) $\endgroup$ – Alan Sep 5 '17 at 15:35
  • $\begingroup$ Yes, I would throw DeleteDuplicates at the list first before moving on. $\endgroup$ – Sjoerd Smit Sep 5 '17 at 15:54
  • $\begingroup$ Here are my tests: In[190]:= RepeatedTiming[(x = ConstantArray[0,Max[#]]; x[[#]] = 1; x)&[{2,1,4}], 20] Out[190]= {6.5*10^-6,{1,1,0,1}} In[191]:= RepeatedTiming[(Normal@SparseArray[Thread[#->1]])&[{2,1,4}], 20] Out[191]= {0.00002,{1,1,0,1}} In[192]:= RepeatedTiming[(Rest@BinCounts[#])&[{2,1,4}], 20] Out[192]= {0.00032,{1,1,0,1}} In[193]:= RepeatedTiming[Reverse[IntegerDigits[Tr[2^(#-1)],2]]&[{2,1,4}], 20] Out[193]= {0.00001,{1,1,0,1}} $\endgroup$ – The Square Cow Sep 6 '17 at 16:00
  • $\begingroup$ Sorry about the formatting, I couldn't get the newlines inside a comment box to work correctly. $\endgroup$ – The Square Cow Sep 6 '17 at 16:02
6
$\begingroup$
Normal@SparseArray[Thread[{1, 5} -> 1]]
(*  {1, 0, 0, 0, 1}  *)

Normal@SparseArray[Thread[{2, 1, 4} -> 1]]
(*  {1, 1, 0, 1}  *)
$\endgroup$
2
$\begingroup$
list = {2, 1, 5};
Normal@SparseArray[Thread[list -> 1]]

or

dat = ConstantArray[0, Max@list];
dat[[{2, 1, 5}]] = 1;
dat
$\endgroup$
0
$\begingroup$
In[253]:= Rest@BinCounts[{1, 5}]

Out[253]= {1, 0, 0, 0, 1}

In[254]:= Rest@BinCounts[{2, 1, 4}]

Out[254]= {1, 1, 0, 1}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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