1
$\begingroup$

I have a list of tuples like so:

{{24, 29}, {155, 161}, {185, 193}, {220, 224}, {229, 234}, {251, 
  256}, {290, 297}, {394, 406}, {568, 586}, {648, 654}, {691, 
  696}, {760, 772}, {852, 856}, {860, 864}, {923, 929}, {954, 
  958}, {984, 992}, {1099, 1108}, {1138, 1144}, {1179, 1185}}

that correspond to intervals on the number line from 1 to 1199. Given this list of tuples I want to construct an array of zeros and ones such that the array takes on the value 1 only between the intervals (ends points included). I have spent the better part of an hour trying to figure this out without any success.

My solution was along the lines of:

ArrSet[ints_] := 
 Module[{x = ConstantArray[0, 1199]}, (Scan[
    x[[#[[1]] ;; #[[2]]]] = 1 &, ints]; x)]

but I can't get it to work. What am I doing wrong?


For context the list of intervals is a value in an association and once I have a working ArrSet the intention is to modify it to ArrSet[key_, ints_] and do a KeyValueMap on the association so that each key/value pair has its on one-zero array.

$\endgroup$
  • 1
    $\begingroup$ You can e.g. define a function pred, that gives 1 or 0 ,depending on the argument being a member of an interval or not. E.g: dat = {{24, 29}, {155, 161}, {185, 193}, {220, 224}, {229, 234}, {251, 256}, {290, 297}, {394, 406}, {568, 586}, {648, 654}, {691, 696}, {760, 772}, {852, 856}, {860, 864}, {923, 929}, {954, 958}, {984, 992}, {1099, 1108}, {1138, 1144}, {1179, 1185}}; pred[x_] = AnyTrue[dat, (#[[1]] <= x <= #[[2]]) & ]; pred /@ Range[1199] $\endgroup$ – Daniel Huber Oct 22 at 14:31
  • $\begingroup$ @DanielHuber That might be a workable solution ... going to try that approach. Do you know what is wrong/breaking in the question's code? That seemed more direct/cleaner but just won't work. $\endgroup$ – ITA Oct 22 at 14:39
  • 3
    $\begingroup$ Yor codes does not work because "&" (function) has a low precedence. If you use brackets it will work: ArrSet[ints_] := Module[{x = ConstantArray[0, 1199]}, (Scan[(x[[#[[1]] ;; #[[2]]]] = 1) &, ints]; x)] $\endgroup$ – Daniel Huber Oct 22 at 15:18
  • $\begingroup$ I would have never figured that on my own ... 😅. $\endgroup$ – ITA Oct 22 at 15:27
  • $\begingroup$ Pay attention to the color of the slots (#). In your code, the slots are pink-ish and they should be green. $\endgroup$ – Sjoerd Smit Oct 22 at 15:52
2
$\begingroup$
tuples = {{24, 29}, {155, 161}, {185, 193}, {220, 224}, {229, 
   234}, {251, 256}, {290, 297}, {394, 406}, {568, 586}, {648, 
   654}, {691, 696}, {760, 772}, {852, 856}, {860, 864}, {923, 
   929}, {954, 958}, {984, 992}, {1099, 1108}, {1138, 1144}, {1179, 
   1185}}; 

sa = SparseArray[Thread[Join @@ Range @@@ tuples -> 1], {1199}]

enter image description here

Normal @ sa

enter image description here

You can also do:

m1 = ConstantArray[0, 1199];
m1[[Join @@ Range @@@ tuples]] = 1;
m1 == Normal @ sa
True
m2 = MapAt[1 &, ConstantArray[0, 1199], List /@ (Span @@@ tuples)];
m2 == Normal @ sa
True
m3 = ConstantArray[0, 1199];
Do[m3[[Span @@ t]] = 1, {t, tuples}]
m3 == Normal @ sa
True
m4 = ReplacePart[ConstantArray[0, 1199], 
        Alternatives @@ Join @@ Range @@@ tuples -> 1];

m4 == Normal @ sa
True
| improve this answer | |
$\endgroup$
  • $\begingroup$ I am trying to avoid saying "Thanks" so let me say: This answer is very detailed and adds more than one way to solve things (when it didn't have to). The MapAt solution and ReplacePart solution are closer to my way of thinking and it is good to know they exist and that there is so much to learn about this language! $\endgroup$ – ITA Oct 23 at 0:26

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.