# Find position avoiding For loop

I have a list:

{a,b,c,d,e,f}


And a function sizeFunc[element_] which returns the size {rows,columns} of the element, for example:

In= sizeFunc[c]
Out= {3,3}


To be clear, all elements are symbolic. I want to find the first element in the above list whose size is not {1,1}. So far I tried:

Position[{a,b,c,d,e,f},(sizeFunc[#]=={1,1})&]


The above is just an attempt, I have no idea how to solve this problem. Thanks a lot for helping.

With for loop (what I want to avoid):

list={a,b,c,d,e,f};
For[k = 1, k <= Length[list], k++,
If[sizeFunc[list[[k]]] != {1, 1},
firstNonScalark = k; Break[];
]
];

• =!= might be useful. Jul 27, 2015 at 20:48
• Do you mean Dimensions[ ]? Jul 27, 2015 at 20:48
• @belisarius What do you mean? Dimensions[] has nothing to do with it, I have my own function sizeFunc[] and I'm searching for the first element from the left whose size is not {1,1} Jul 27, 2015 at 20:51
• LengthWhile[list, sizeFunc[#] == {1,1}&]+1. I think For is pretty awful in Mathematica and can always be avoided. If you do need a procedural loop, use Do which at least localizes the iterator, and is more compact and more readable. Jul 27, 2015 at 20:51
• @Szabolcs Thanks it works BUT when no element in a list has size other than {1,1}, the returned value exceeds list dimensions by 1. How do I bound the value to the length of the list? Jul 27, 2015 at 21:01

I'll define a sizeFunc to play with:

Clear[sizeFunc]
sizeFunc[a] = {1, 1}; sizeFunc[b] = {1, 1}; sizeFunc[c] = {3, 2};
sizeFunc[d] = {2, 4}; sizeFunc[e] = {1, 1}; sizeFunc[f] = {1, 1};


UPDATE:

OP mentioned the desired behavior when all elements return {1, 1}. Taking that into consideration, one can define the following function:

firstnonscalar[l_List] := Module[
{position},
If[(position = First@FirstPosition[l, el_ /; sizeFunc[el] != {1, 1}]) != "NotFound",
position,
Length[l]
]
]


As requested, this will return the position of the first element whose sizeFunc does not return {1, 1}, or alternatively the Length of the list, which is the position of the last element.

In my understanding of your question, you want the (position of) the first element whose sizeFunc is not {1,1}.

If you want the element itself, then the following would work:

SelectFirst[{a, b, c, d, e}, sizeFunc[#] != {1, 1} &]
(* Out: c *)


If you want the position of that element in the list, then the following would work instead:

First@FirstPosition[{a, b, c, d, e}, el_ /; sizeFunc[el] != {1, 1}]
(* Out: 3 *)


Here is what happens to these functions if there are no elements for which sizeFunc is different from {1, 1}:

Clear[sizeFunc]
sizeFunc[a] = {1, 1}; sizeFunc[b] = {1, 1}; sizeFunc[c] = {1, 1};
sizeFunc[d] = {1, 1}; sizeFunc[e] = {1, 1}; sizeFunc[f] = {1, 1};
SelectFirst[{a, b, c, d, e}, sizeFunc[#] != {1, 1} &]
First@FirstPosition[{a, b, c, d, e}, el_ /; sizeFunc[el] != {1, 1}]

(* Out:
Missing["NotFound"]
"NotFound"
*)


You didn't specify what to do in that case, so I'll leave the handling of those cases to whatever is best to your application.

• Thanks a lot. If you want to modify your answer, the handling should be to output the position of the last element of the list. Jul 27, 2015 at 21:27
• Upvote for FirstPosition. I always feel silly putting those two 1s in arguments to Position and wonder why levelspec isn't the last argument.
– Ian
Jul 27, 2015 at 21:30
• @space_voyager OK thanks for the clarification; I included that in an ad hoc function. Jul 27, 2015 at 21:41
• @Ian Thank you. To be honest, I find the syntax and output of Position rather confusing myself, so I often have to look up to get just right. Jul 27, 2015 at 21:42
• @MarcoB thanks a lot! Jul 27, 2015 at 22:00

If your size function behaves something like this:

sizeFunc[x_] := {1, 1}
sizeFunc[d] := {3, 2, 1}


then Select can get you the first element matching your negative criterion. Like this:

Select[{a, b, c, d, e, f}, sizeFunc[#]!={1, 1} &, 1]


If you want to use Position to get the position of the element in the list (rather than the element itself), you have to supply a pattern rather than a criterion.

Position[{a, b, c, d, e, f}, x_ /; sizeFunc[x] != {1, 1}, 1, 1]

• Position[{a, b, c, d, e, f}, x_ /; sizeFunc[x] != {1, 1}, 1]]+1 did the trick! Thank you. Jul 27, 2015 at 21:26

FirstPosition allows for a default value:

sizeFunc[a | b | d | e | f] = {1, 1};
sizeFunc[c] = {2, 3};

list = {a, b, c, d, e, f};

FirstPosition[list, _?(sizeFunc[#] != {1, 1} &), {Length @ list}]

{3}

sizeFunc[c] = {1, 1};

FirstPosition[list, _?(sizeFunc[#] != {1, 1} &), {Length @ list}]

{6}


Without FirstPosition one might use:

Position[list, _?(sizeFunc[#] != {1, 1} &), 1, 1] /.
{{p_List} :> p, {} :> {Length@list}}

• I didn't know that! Thank you for pointing that out. That makes for a nice terse one-liner. (+1) Jul 28, 2015 at 4:42
• @MarcoB Thanks for the link correction! I also added a method using Position that is reasonably clean. Jul 28, 2015 at 15:33