1
$\begingroup$

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.

$\endgroup$

2 Answers 2

6
$\begingroup$
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]
$\endgroup$
5
  • $\begingroup$ 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... $\endgroup$
    – Leo
    Jun 1, 2014 at 21:22
  • $\begingroup$ @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. $\endgroup$
    – ciao
    Jun 1, 2014 at 21:26
  • 2
    $\begingroup$ @Leon Lampret - maybe a little bit easier to read for us starters: First@Position[list, a_ /; a != 1] $\endgroup$
    – eldo
    Jun 1, 2014 at 21:38
  • $\begingroup$ @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$. $\endgroup$
    – Leo
    Jun 18, 2014 at 2:23
  • $\begingroup$ @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... $\endgroup$
    – ciao
    Jun 18, 2014 at 5:04
5
$\begingroup$
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} *)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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