2
$\begingroup$

Assuming we have a list below, it has real number elements and complex numbers, how can I quickly find if the list has any Real number that its value is less than 1.0?

 lis = {3 Sqrt[354], Sqrt[2962], Sqrt[2746], 3 Sqrt[282], Sqrt[2338], 
  Sqrt[2146], 3 Sqrt[218], Sqrt[1786], Sqrt[1618], 27 Sqrt[2], Sqrt[
  1306], Sqrt[1162], 3 Sqrt[114], Sqrt[898], Sqrt[778], 3 Sqrt[74], 
  Sqrt[562], Sqrt[466], 3 Sqrt[42], Sqrt[298], Sqrt[226], 9 Sqrt[2], 
  Sqrt[106], Sqrt[58], 3 Sqrt[2], I Sqrt[14], I Sqrt[38], 3 I Sqrt[6],
   I Sqrt[62], I Sqrt[62], 3 I Sqrt[6], I Sqrt[38], I Sqrt[14], Sqrt[
  1.2], Sqrt[58], Sqrt[1.06], 9 Sqrt[2], Sqrt[226]}

I am also considering if we can find methods to filter any real or complex numbers with specific values in any types list (e.g. there are some string elements mixed with real and complex number elements in a given list). But this could be another question and isn't necessary for my example. Please leave some advice if you interested! Thanks in advance!

$\endgroup$
2
  • $\begingroup$ I would numericize first, something like FreeQ[N @ lis, _Real?(LessThan[1])] $\endgroup$
    – Carl Woll
    Dec 21, 2017 at 2:30
  • 1
    $\begingroup$ One of the most straightforward: Select[lis, Re[#] < 1 && Im[#] == 0 &] $\endgroup$
    – Michael E2
    Dec 21, 2017 at 3:56

5 Answers 5

4
$\begingroup$
Pick[lis, Internal`RealValuedNumericQ@# && # < 1 & /@ lis]

{}

Pick[lis, Internal`RealValuedNumericQ @ # && # < 5 & /@ lis]

{3 Sqrt[2], 1.09545, 1.02956}

Pick combined with @aardvark2012's selector approach and exploiting the fact that Negative, Positive, NonPositive ... are Listable:

Pick[lis, NonPositive[lis - 5]]

{3 Sqrt[2], 1.09545, 1.02956}

This seems to be the fastest of methods posted so far.

$\endgroup$
4
  • $\begingroup$ +1. I wonder how many "How do I select elements satisfying condition $P$?" questions the site has, all with virtually the same large set of alternatives. BTW, I was going to use Developer`RealQ /@ N@lis, but then thought better of it for some reason $\endgroup$
    – Michael E2
    Dec 21, 2017 at 3:35
  • $\begingroup$ @MichaelE2, thank you for the upvote. I agree re the number of questions with answers using Pick/Select/Cases... . FWIW, this one is more about specifying the condition/selector to get Reals. $\endgroup$
    – kglr
    Dec 21, 2017 at 3:42
  • 1
    $\begingroup$ Something like Re[x] < 1 && Im[x] == 0, in some form or other, seems a kinda straightforward, first-guess sort of thing to try to me (almost Nasser's). $\endgroup$
    – Michael E2
    Dec 21, 2017 at 3:53
  • $\begingroup$ Thank you! Very helpful! $\endgroup$
    – leon365
    Dec 21, 2017 at 15:39
2
$\begingroup$

how can I quickly find if the list has any Real number that its value is less than 1.0?

One way might be

Cases[ReIm[lis],{x_,y_}/;y==0&&x<1]
(*{} *)

Example

 lis={.7, .7I .7+1, 2, 2I, 2+1 I};
 Cases[ReIm[lis],{x_,y_}/;y==0&&x<1 :> Complex[x,y]]

Mathematica graphics

Using the above, you can now add any kind of checks on x and y to filter any kind of number you want. For example, to look for pure complex numbers:

 Cases[ReIm[lis],{x_,y_}/;x==0&&y!=0 :> Complex[x,y]]

Mathematica graphics

To look for number with real and complex parts

  Cases[ReIm[lis],{x_,y_}/;x!=0&& y!=0 :> Complex[x,y]]

Mathematica graphics

And so on.

$\endgroup$
2
$\begingroup$

Here's a way using Pick:

Pick[lis, UnitStep[1 - Re@#] + I*Im@# &@N@lis, 1]
(*  {}  *)

lis2 = lis/10;
Pick[lis2, UnitStep[1 - Re@#] + I*Im@# &@N@lis2, 1]
(*  {Sqrt[29/2]/5, 3/(5 Sqrt[2]), 0.109545, Sqrt[29/2]/5, 0.102956}  *)

UnitStep[1 - Re@#] returns 1 if the real part of the number is less than 1. And I*Im@# is 0 if the number is real; otherwise, it will have a nonzero imaginary part and be a number of type Complex.

$\endgroup$
2
$\begingroup$

You may use Selectand Element.

Select[# ∈ Reals && # < 1 &]@lis
{}

There appear to be no items that are both in the reals and less than one.

If you do not need the items but only the result of the test then you could place in an If and test the Length.

If[
 Length@Select[# ∈ Reals && # < 1 &]@lis > 0,
 True,
 False]
False

Hope this helps.

$\endgroup$
2
$\begingroup$

There's always Select:

Select[lis, Negative[# - 1] &]

Negative is nice because it'll work on pretty much anything, but only return True if the argument is a negative real number. Testing it on a longer list:

SeedRandom[123456]
lis = RandomSample[
  Join[RandomReal[2, 10], RandomComplex[{-1 - I, 1 + I}, 10]], 
 20];

Select[lis, Negative[# - 1] &]

(* {0.982588, 0.86323, 0.0961836, 0.963281, 0.780961, 0.225647, 0.34709} *)

But the question is a little ambiguous -- the phrase "how can I quickly find if the list has any Real number that its value is less than 1.0?" indicates that you don't actually care what the numbers are, just whether they're there or not. If that's what you're really after, you can do:

CountsBy[lis, Negative[# - 1] &][True]

(* 7 *)

As far as generalization goes, Select is so incredibly generalizable that it's hard to know where to start. If, say, there are strings involved in your list, these approaches still work as they are:

SeedRandom[123456]
lis = RandomSample[
  Join[RandomReal[2, 10], RandomComplex[{-1 - I, 1 + I}, 10], 
   RandomChoice[CharacterRange["a", "z"], 10]], 30]

Select[lis, Negative[# - 1] &]
CountsBy[lis, Negative[# - 1] &][True]

(* {0.0961836, 0.982588, 0.225647, 0.780961, 0.963281}
   5 *)
$\endgroup$

Your Answer

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

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