2
$\begingroup$

Let me start with an example:

data = Partition[RandomInteger[50, 40], 3];
s = {10, 50};

I'd like to choose the first element of each sublist subject to the selector "s". and then find the maximum of the list by the last element. one solution is using Table

Table[
   MaximalBy[Select[data, #[[1]] <= s[[i]] &], Last]
 , {i,   Length[s]}]

but this requires an itrator (i).

The other solution is using an auxiliary function:

f[i_] = (#[[1]] <= s[[i]]) &;
MaximalBy[Select[data, f[#]], Last] & /@ Range[Length[s]]

I am wondering if there is a way to have one liner code ( by using MapThread for instance ).

$\endgroup$
2
  • 1
    $\begingroup$ According to your comment on eldo's post, you seem to be interested in speed. If that is the case, it is worth waiting a while before accepting an answer. (In general this is good practice, because it encourages more answers.) There are likely many ways to do this problem, and these kinds of questions tend to attract a lot of answers. $\endgroup$
    – march
    Commented Aug 30, 2017 at 19:49
  • $\begingroup$ Cases[data, {a_ /; a <= i, __}] is slightly faster than Select[data, #[[1]] <= s[[i]] &] in this case (roughly a factor of 2). $\endgroup$
    – march
    Commented Aug 30, 2017 at 20:03

2 Answers 2

1
$\begingroup$
SeedRandom@1;
data = Partition[RandomInteger[50, 40], 3];

{{20, 1, 48}, {2, 6, 3}, {16, 28, 33}, {31, 33, 17}, {12, 44, 40}, {30, 24, 2}, {25, 11, 21}, {14, 12, 1}, {15, 29, 19}, {0, 50, 44}, {50, 29, 20}, {21, 48, 47}, {14, 17, 3}}

s = {10, 50};

MaximalBy[Last] /@ Map[Cases[data, {a_, __} /; a <= #] &] @ s

{{{0, 50, 44}}, {{20, 1, 48}}}

Or

MaximalBy[Last] /@ Function[{x}, Select[data, First@# <= x &], Listable] @ s
$\endgroup$
1
  • $\begingroup$ Thank you. I like your first solution. Making a function listable is not efficient in Mathematica other than internal functions, it would be slow for a large number of data. I didn't know MaximalBy can take only one argument making an operator. $\endgroup$ Commented Aug 30, 2017 at 19:34
1
$\begingroup$

A fairly fast method is:

SeedRandom[1]
data = Partition[RandomInteger[50, 40], 3];
s = {10, 50};

(SortBy[Last] /@ 
   (Pick[data, #] & /@
     NonPositive[{#, #} &@data[[;; , 1]] - s]
    )
  )[[;; , -1]]

{{0, 50, 44}, {20, 1, 48}}}

SortBy appears to be substantially faster than MaximalBy in this case:

RepeatedTiming[
 MaximalBy[Last] /@ 
  (Pick[data, #] & /@
    NonPositive[{#, #} &@data[[;; , 1]] - s]
   )
 ]

RepeatedTiming[
 (SortBy[Last] /@ 
    (Pick[data, #] & /@
      NonPositive[{#, #} &@data[[;; , 1]] - s]
     )
   )[[;; , -1]]
 ]

{0.000149, {{{0, 50, 44}}, {{20, 1, 48}}}}

{0.000035, {{0, 50, 44}, {20, 1, 48}}}

$\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.