Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have table like this:

t = {False, False, False, 4.5, 6.789, 1.23, 0.98, False, False}

and I want to know how many False values I have at the beginning and at the end of the table.

I made:

size = Length[t]
t = Cases[t,Except[False]];
size2 = Length[t]
diff = size - size2

But this counts number of all 'False' values inside the table. But I want to know how many is at the beginning and how many at the end (so i my example I have: 3 at the beginning and 2 at the end). How can I solve that?

share|improve this question
    
If the list is all False, what you want, the length of the lsit or the numbers at the beginning and at the end separately? (It's an edge-case in which the numbers of False and from the beginning and from the end are each equal to the length of the list. Based on your example, I would assume in the case of all False you want the length and otherwise the sum of the runs. But please clarify.) –  Michael E2 Jan 11 at 20:17
add comment

5 Answers 5

up vote 10 down vote accepted

Here is one way:

before= LengthWhile[t, Not]

(* 3  *)

after = LengthWhile[Reverse[t], Not]

(* 2  *)
share|improve this answer
    
Very nice solution, I didn't get the idea about reversing the table. Thanks! –  Ziva Jan 11 at 11:55
    
@Ziva In fact, reversing might not be optimal for long lists, you might be better off explicitly looping from the end then. For longer lists, however, mixing Boolean values with numbers may not be a good practice anyway. –  Leonid Shifrin Jan 11 at 11:56
    
@Ziva Thanks for the accept, but I'd wait for some more answers before accepting one - this way you will encourage more solutions, including perhaps better ones. –  Leonid Shifrin Jan 11 at 11:57
    
+1 but IMHO it would be cleaner to eliminate Function: LengthWhile[t, Not]. –  Mr.Wizard Jan 11 at 13:45
    
@Mr.Wizard Agreed. Edited. –  Leonid Shifrin Jan 11 at 14:57
add comment
z = Split[t];
Map[Length, {First[z], Last[z]}]

(* {3, 2} *)
share|improve this answer
1  
I get about a 40% reduction in computation time with SplitBy relative to LengthWhile. –  bobthechemist Jan 11 at 13:16
2  
I don't understand what you intend with SplitBy[t, False]. I believe it is equivalent to Split[t] here. –  Mr.Wizard Jan 11 at 13:28
    
Not SplitBy, Split. :-) I would write: Length /@ Split[t][[{1, -1}]], Also, note that this method will only work if one is certain that the list begins and ends with False; it cannot handle a "zero count" case. –  Mr.Wizard Jan 11 at 13:34
add comment

Gives you the leading and trailing as a list:

LengthWhile[#, ! # &] & /@ {t, t // Reverse}

If you need to assign to symbols, e.g.,

{front, back}=LengthWhile[#, ! # &] & /@ {t, t // Reverse}

Edit: Just saw L.S.'s answer - same idea. As he notes, for huge lists reverse may not be the best way. I find the idiom somelist[[-1;;1;;-1]] a faster way, and depending on what you know about the structure of the data, other ways may be faster.

share|improve this answer
add comment

Here's a rules-based solution as well so that we have one of those too:

t /. {f : False ..., Except[False] .., l : False ...} :> {Length[{f}], Length[{l}]}
share|improve this answer
2  
I thought of this one too, but unfortunately it is extremely inefficient due to Mathematica's failure to optimize pattern matching. –  Mr.Wizard Jan 11 at 14:59
add comment

I came up with this and then noticed it is a variation on Anon's approach:

 # /. {___, x:Longest[False ...], __, y:Longest[False ...]} :> {Length[{x}], Length[{y}]} &

The same idea, with a named function:

f[list_] := Length[list /. {___, x : Longest[False ...], __} :> {x}]

Example:

 {f[t], f[Reverse[t]]}

{3, 2}

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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