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$
  • 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 Aug 30 '17 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 Aug 30 '17 at 20:03
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$
  • $\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$ – Amir Jalali Aug 30 '17 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, privacy policy and cookie policy

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