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 want to know is there any one line code to find position of first nonzero number without calculating position of all non zero numbers. For example,

A = {0, 0, 0, 1, -2, -1, 0};
First[Flatten[Position[A, _?(# != 0 &)], 1]]

will give me position of first non zero number. But first it calculate position of all non zero number. Is there any way to stop position function when it found first non zero number?

share|improve this question
add comment

8 Answers

up vote 12 down vote accepted

You can specify number of object to return in Position. For example,

list = RandomInteger[{-5, 5}, 100000];
Position[list, _?(# != 0 &), 1, 1] // AbsoluteTiming

{0.003050, {{1}}}

Position[list, _?(# != 0 &)] // First // AbsoluteTiming

{0.138709, {1}}

share|improve this answer
add comment
SeedRandom[1];
LengthWhile[RandomInteger[{-5, 5}, 100000], # == 0 &] + 1
(* 1 *)
share|improve this answer
    
you mean by this? LengthWhile[list, # == 0 &] + 1 –  halmir Oct 4 '13 at 19:03
    
@halmir yes, I corrected it while you were writing the comment :) –  belisarius Oct 4 '13 at 19:04
add comment

While this certainly isn't a contender for speed, patterns are fun:

A /. {z : Longest[(0 | 0`) ...], ___} :> Length@{z} + 1
share|improve this answer
add comment

We can use SparseArray. It computes all the positions, but it's a bit faster than Position, esp. on packed arrays, since Position unpacks a packed array.

First @ SparseArray[packedarray]["NonzeroPositions"]

or

First @ SparseArray[Developer`ToPackedArray @ unpackedlist]["NonzeroPositions"]

Timings on ten random lists:

SeedRandom[1];
n = 10;
list = RandomChoice[{0.9, 0.1} -> {0, 1}, {n, 100000}];
packedlist = Developer`ToPackedArray @ list;

Table[
  First @ SparseArray[Developer`ToPackedArray @ list[[i]]]["NonzeroPositions"],
  {i, n}] // AbsoluteTiming
Table[
  Position[list[[i]], _?(# != 0 &), 1, 1],
  {i, n}] // AbsoluteTiming

Table[
  First @ SparseArray[packedlist[[i]]]["NonzeroPositions"],
  {i, n}] // AbsoluteTiming
Table[
  Position[packedlist[[i]], _?(# != 0 &), 1, 1],
  {i, n}] // AbsoluteTiming

{0.007372, {{15}, {28}, {4}, {20}, {13}, {2}, {8}, {7}, {42}, {9}}}
{0.009183, {{{15}}, {{28}}, {{4}}, {{20}}, {{13}}, {{2}}, {{8}}, {{7}}, {{42}}, {{9}}}}

{0.005098, {{15}, {28}, {4}, {20}, {13}, {2}, {8}, {7}, {42}, {9}}}
{0.024295, {{{15}}, {{28}}, {{4}}, {{20}}, {{13}}, {{2}}, {{8}}, {{7}}, {{42}}, {{9}}}}


Compiled

It's rather straightforward in an imperative paradigm:

firstnzp = Compile[{{list, _Integer, 1}},
  Do[If[list[[i]] != 0, Return[i]], {i, Length@list}],
  RuntimeOptions -> "Speed"
  ]

And fast:

Table[firstnzp @ list[[i]], {i, n}] // AbsoluteTiming

{0.004164, {15, 28, 4, 20, 13, 2, 8, 7, 42, 9}}

share|improve this answer
add comment

Just for fun:

ArrayRules[list][[1, 1, 1]]
share|improve this answer
add comment

Comparing:

Position[s, e_ /; e != 0] // Trace

Position[s, e_ /; e != 0, 1, 1] // Trace

The number of matched positions to be found at certain levels can be specified, then Position, searching left to right, stops as soon as it finds that many.

share|improve this answer
add comment

Yet another compiled function:

firstnzp2 = Compile[{{list, _Integer, 1}}, 
  Module[{n = 0}, While[list[[++n]] == 0]; n], 
  CompilationTarget -> "C", RuntimeOptions -> "Speed"];

The speed is the same as Michael's compiled code after addition CompilationTarget -> "C".

Or one-liner:

1 + Total@UnitStep[-Accumulate@Unitize[list]]
share|improve this answer
add comment

If you are interested in manual solution, this might be helpful as well.

    f[x_] := (If[x > 0, Return[Position[A, x][[1, 1]]]]; x)

sparr = SparseArray[{{1, 400} -> 2, {1, 90000} -> 2}]
A = Normal[sparr][[1]];
  Catch[Table[If[f[A[[i]]] > 0, Throw[f[A[[i]]]], f[A[[i]]]], {i, Length[A]}]]

400 (Timing 0.06 Sec)

sparr = SparseArray[{{1, 90000} -> 2}]
A = Normal[sparr][[1]];
  Catch[Table[If[f[A[[i]]] > 0, Throw[f[A[[i]]]], f[A[[i]]]], {i, Length[A]}]]

90000 (1.11 Sec)

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.