6
$\begingroup$

I have a series of lists of this form: {1, 1, 1, 1, 0, 0, 1, 1}. I would like to perform a survival analysis on these lists. To do that, I need a code that would check each elements of these lists, do nothing as long as these are 1s, but as soon as one element is 0, it would change all the following elements to zero.

As an example, this code would transform the above list to {1, 1, 1, 1, 0, 0, 0, 0}. I can't seem to find a way to do this. Thanks.

$\endgroup$
6
$\begingroup$

Let's take

list = {{1, 1, 1, 0, 1, 0, 1}, {1, 1, 1, 1, 1, 1, 1, 1}, {0, 1, 1, 1}, {0, 0}}

and run

list /. {x : 1 ___, z : 0 ___, y___} :> PadRight[{x}, Length@{x, z, y}]

{{1, 1, 1, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0}}


Original answer:

Cases[list, {x : 1 ___, 0, y___} :> PadRight[{x}, Length @ {x, 0, y}]]

{{1, 1, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0}}

Equivalents:

Cases[list, {x : 1 ___, 0, y___} :> Flatten @ {x, 0, ConstantArray[0, Length @ {y}]}]

Cases[list, {x : 1 ___, 0, y___} :> Join @@ {{x}, {0}, ConstantArray[0, Length @ {y}]}]

Fails when a list is composed only of 1s.

UPDATE:

This is a fix:

Cases[list, {Longest[x : 0 .. | 1 ..], y___} :> PadRight[{x}, Length @ {x, y}]]
$\endgroup$
  • $\begingroup$ Thanks a lot, works great. So 1___ is the part of the list that is composed of successive 1s? $\endgroup$ – EBassal Oct 26 '16 at 17:44
  • 1
    $\begingroup$ 1___ is a pattern saying to take the initial 1s in the list; the three underscores ___ indicate to take as many (initial) 1s there are, including the case when there are no 1s in the beginning. Two underscores, __ would indicate as many 1s there are but at least one, so it would fail to return the proper answer in the case of list[[3]]. $\endgroup$ – corey979 Oct 26 '16 at 17:51
  • $\begingroup$ Just as a curio: to get all succesive 1 see here. $\endgroup$ – corey979 Oct 26 '16 at 18:07
  • $\begingroup$ I'm not sure but, I think there might be a problem with the solution that you proposed. I had initially 137 lists, but when I apply your function I only get 103 as output. It is important that I keep the same number of sublists at the end. Would you know how to correct that? $\endgroup$ – EBassal Oct 26 '16 at 18:41
  • 1
    $\begingroup$ I edited accordingly; provided a different, working, method. $\endgroup$ – corey979 Oct 26 '16 at 19:03
6
$\begingroup$

Edit

As kglr points out in a comment:

FoldList[Times]/@list

Original Answer

FoldList[Times, #] & /@ list 

{{1, 1, 1, 0, 0, 0, 0}, {1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0}}

$\endgroup$
  • $\begingroup$ (+1) You could also use the operator form FoldList[Times]/@list. $\endgroup$ – kglr Oct 26 '16 at 19:27
  • $\begingroup$ @kglr Thanks! Have added your code to the answer. $\endgroup$ – user1066 Oct 26 '16 at 19:34

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.