1
$\begingroup$

I have a formula which is producing a large (hundreds of elements) list of complex numbers of the simple form $x+iy$.

However I'm only interested in the one value which satisfies the conditions:

  1. The imaginary part is the least negative value in the list

  2. The real part is positive.

What can write that will pick out this value and display it for me?

$\endgroup$
2
$\begingroup$

Rather complex one: first Select, then SortBy and pick the first one.

SortBy[Select[c, Re[#] > 0 && Im[#] < 0 &], Abs[Im[#]] &][[1]]
$\endgroup$
1
$\begingroup$

The question states two conditions that are to be satisfied by the number sought:

  1. The imaginary part is the least negative value in the list

  2. The real part is positive.

Note that the number sought is not the one with the least negative imaginary part among the numbers in the list that have a positive real part. It is the one that has the least of all the numbers in the list. If all the numbers with the least negative imaginary part have negative real parts, then there is no number satisfying the conditions.

Note also -- at least to my mind -- that the number with the least negative imaginary part has the least imaginary part of all the numbers in the list and the part is negative. The condition is not that the imaginary part is least in absolute value.

[Remark: Currently, the OP has accepted an answer in which a method for finding the number with greatest negative imaginary part (least in absolute value) among only those numbers with a positive real part.]

In any case, here is a solution to the question as stated:

findit = Select[MinimalBy[#, Im], Positive @* Re] &

Examples

findit @ {1 - 2 I, -3 - 2 I}
(* {1 - 2 I} *)

findit @ {1 + 2 I, -3 + I}
(* {} *)

SeedRandom[0];
c = RandomComplex[{-1 - 1 I, 1 + I}, 20];
findit @ c
(* {0.753377 - 0.818516 I} *)

Pre V10 version: findit = Select[MinimalBy[#, Im], Positive[Re[#]] &] &

$\endgroup$
  • $\begingroup$ +1. I understand it, the way you understand it. $\endgroup$ – RunnyKine Aug 6 '14 at 2:13
0
$\begingroup$

An efficient method is to split real and imaginary parts, and use MaximalBy rather than SortBy as this avoids sorting the entire list:

SeedRandom[0]
c = RandomComplex[{-1 - I, 1 + I}, 20];

Pick[c, Sign @ ReIm @ c, {1, -1}] // MaximalBy[Im]
{0.809571 - 0.134575 I}

This is about three times as fast as m0nhawk's code as well as more concise:

SeedRandom[0]
c = RandomComplex[{-1 - I, 1 + I}, 1*^5];

SortBy[Select[c, Re[#] > 0 && Im[#] < 0 &], Abs[Im[#]] &][[1]]     // RepeatedTiming

Pick[c, Sign @ ReIm @ c, {1, -1}] // MaximalBy[Im]                 // RepeatedTiming
{0.155, 0.236911 - 0.0000919759 I}

{0.0449, {0.236911 - 0.0000919759 I}}
$\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.