6
$\begingroup$

Assume I have an ordered, ascending list {1,4,10,12,20}. I want to find the smallest position of an element of the list such that the element is not less than 11? The position in question is 4.

How to do this easily?

$\endgroup$
1
  • $\begingroup$ @user1066: A nice idea. But your list is not the same as mine. 11 is not in the list. $\endgroup$ Commented Jun 27, 2020 at 17:31

7 Answers 7

11
$\begingroup$
FirstPosition[{1, 4, 10, 12, 20}, _?(# >= 11 &)]

(* Out: {4} *)

If you want just the number $4$, then use First@FirstPosition[...].

$\endgroup$
2
  • 3
    $\begingroup$ you need to add = after >. $\endgroup$ Commented Jun 27, 2020 at 17:10
  • $\begingroup$ @TooFatManNoNeck You're right! Fixed, thank you, and thanks for the accept as well. $\endgroup$
    – MarcoB
    Commented Jun 27, 2020 at 18:25
6
$\begingroup$

This question is closely related to the question Best way to insert element into an ordered list at the correct position? , where it was noted that Leonid Shifrin's bsearchMax from this answer is a fast way to solve the problem. Like flinty's answer it uses a binary search but it appears to be faster.

bsearchMax[{1, 4, 10, 12, 20}, 11]

4

For a list of decent size, bsearchMax can be orders of magnitude faster than FirstPosition.

$\endgroup$
5
$\begingroup$

A couple of slower alternatives to FirstPosition:

data = {1, 4, 10, 12, 20};

Position[data, SelectFirst[data, # >= 11 &]][[1, 1]]

Needs["Combinatorica`"]; Ceiling@BinarySearch[data, 11]
$\endgroup$
4
$\begingroup$

As the list is in ascending order, maybe:

1+LengthWhile[{1, 4, 10,12,20}, # <11 &]

4

A slight variation on the FirstPosition answer of MarcoB (originally posted as a comment):

FirstPosition[UnitStep[{1,4,10,12,20}-11],1]

{4}

$\endgroup$
2
$\begingroup$
list = {1, 4, 10, 12, 20, 12};

Using PositionIndex

First @ First @ KeySelect[GreaterEqualThan @ 11] @ PositionIndex[list]

4

$\endgroup$
2
$\begingroup$
list = {1, 4, 10, 12, 20, 12};

Using GroupBy:

First[Keys@GroupBy[Thread[Range@Length@# -> #] &@list, #[[2]] >= 11 &][True]]

4

$\endgroup$
2
$\begingroup$
list = {1, 4, 10, 12, 20}
list~Join~{11} // Sort // FirstPosition[11]

or

SplitBy[list, #1 < 11 &] // 1 + Length@First @# &

{4}

$\endgroup$

Your Answer

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

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