# Counting 'False' values at the ends of a list

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.

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?

-
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 '14 at 20:17

Here is one way:

before= LengthWhile[t, Not]

(* 3  *)

after = LengthWhile[Reverse[t], Not]

(* 2  *)

-
Very nice solution, I didn't get the idea about reversing the table. Thanks! – Ziva Jan 11 '14 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 '14 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 '14 at 11:57
+1 but IMHO it would be cleaner to eliminate Function: LengthWhile[t, Not]. – Mr.Wizard Jan 11 '14 at 13:45
@Mr.Wizard Agreed. Edited. – Leonid Shifrin Jan 11 '14 at 14:57
z = Split[t];
Map[Length, {First[z], Last[z]}]

(* {3, 2} *)

-
I get about a 40% reduction in computation time with SplitBy relative to LengthWhile. – bobthechemist Jan 11 '14 at 13:16
I don't understand what you intend with SplitBy[t, False]. I believe it is equivalent to Split[t] here. – Mr.Wizard Jan 11 '14 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 '14 at 13:34

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.

-

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}]}

-
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 '14 at 14:59

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}

-