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.

How can I find in a list l the positions of all elements satisfying a boolean function f.

For example, how can I pick in {1, 1, 1, 3, 2, 4, 1, 4, 1, 1, 2, 1} the first element that does not equal 1?

A minimized version of an aswer (short code) is welcome.

share|improve this question

2 Answers 2

up vote 4 down vote accepted
list = {1, 1, 1, 3, 2, 4, 1, 4, 1, 1, 2, 1}

(* get position of first non-one *)
Position[list, _?(# != 1 &), 1, 1]

(* get positions of all non-one *)
Position[list, _?(# != 1 &)]

(* get value of first non-one *)
First@Cases[list, _?(# != 1 &)]

(*
{{4}}

{{4},{5},{6},{8},{11}}

3
*)

Many other ways (see, e.g. Pick, Except, Select for a start ... )

For your arbitrary function f, just use it in constructs like above, e.g.:

Position[list, _?f]
share|improve this answer
    
Hmm, I'm not familiar with _?, this seems really slick. So this is a way to turn a boolean expression into a pattern? Can't find _? in the Mathematica 6 manual... –  Leon Jun 1 at 21:22
    
@LeonLampret: As I said, there are many ways to do this kind of thing, I'm sure you'll see others in answers. See here for the pattern test (?) info. You might also look at condition, another way this kind of thing can be done. –  rasher Jun 1 at 21:26
2  
@Leon Lampret - maybe a little bit easier to read for us starters: First@Position[list, a_ /; a != 1] –  eldo Jun 1 at 21:38
    
@eldo: Why doesn't your or rasher's code work: n=3; l={{2,1,3},{1,3,2}}; Position[l, _?(#[[n]]!=n&), 1, 1] First@Position[l, a_ /; a[[n]]!=n] It should return $2$. –  Leon Jun 18 at 2:23
    
@LeonLampret: Do this Position[l, _?((Sow[#]; #[[n]] != n) &), 1, 1] // Reap ... observe the result. Now, try this Position[l, _?(#[[n]] != n &), 1, 1, Heads -> False] for your sublist case. Reply back if not clear why this is... –  rasher Jun 18 at 5:04
list = {1, 1, 1, 3, 2, 4, 1, 4, 1, 1, 2, 1};

Some alternatives to Position:

f = (# != 1 &) (* say *)
Pick[Range[Length@list], f /@ list]
(* {4,5,6,8,11} *)

Select[Range[Length@list], f@list[[#]] &]
(* {4,5,6,8,11} *)

Select[Range[Length@list], f@list[[#]] &, 1]
(* {4} *)

Join@@ MapIndexed[If[f@#, #2, ## &[]] &, list]  (* credit for ##&[]: Mr.W and ?? *)
(* {4,5,6,8,11} *)

Catch@MapIndexed[If[f@#, Throw[#2]] &, list]
(* {4} *)
share|improve this answer

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.