4
$\begingroup$

Say I have a list like this

a={-7.61575, 7.5, -6.84206, 6.64598, 5.7654, -5.64823, 4.69842, -4.5, \
-1.86729 + 1.90939 I, -1.86729 - 1.90939 I, 0.905621 + 1.98443 I, 
0.905621 - 1.98443 I, 0.631991 + 1.96227 I, 0.631991 - 1.96227 I, 
0.327801 + 1.9312 I, 0.327801 - 1.9312 I}

How do I define a function that counts the number of real and complex entries 0n this list?

$\endgroup$
4
  • 2
    $\begingroup$ Not sure what format you want, but you might start with CountsBy[a,Head] $\endgroup$
    – lericr
    Commented Sep 6, 2022 at 10:10
  • 1
    $\begingroup$ Try: Count[a, _Real] and Count[a, _Complex] $\endgroup$ Commented Sep 6, 2022 at 10:39
  • 7
    $\begingroup$ Is 1. + 0. I a complex or real number for you? $\endgroup$ Commented Sep 6, 2022 at 11:21
  • $\begingroup$ {Head@#[[1]], #[[2]]} & /@ Tally[a, Head[#1] === Head[#2] &] $\endgroup$
    – Bob Hanlon
    Commented Sep 6, 2022 at 18:58

4 Answers 4

4
$\begingroup$

Note that in Mathematica, 0 (the exact integer) and 0. (the floating-point zero) are equal: 0==0. returns True. We can use this trick to split the numbers into those with zero imaginary part ($\mathbb{R}$) and those with non-zero imaginary part ($\mathbb{C}\setminus\mathbb{R}$):

a = {1., 1. I, 1. + 0. I};
CountsBy[a, Im[#] == 0 &]
(*    <|True -> 2, False -> 1|>    *)

We thus have two real numbers (True) and one truly complex one (False). This result differs from that obtained by looking at the Head of the list entries: CountsBy[a, Head] returns <|Real -> 1, Complex -> 2|>, which seems wrong.

For the paranoid, a more general formulation uses PossibleZeroQ to check for zero-ness of the imaginary part:

CountsBy[a, PossibleZeroQ@*Im]
(*    <|True -> 2, False -> 1|>    *)
$\endgroup$
7
$\begingroup$
Counts[Head /@ a]

<|Real -> 8, Complex -> 8|>

or

Length@Cases[a, #] & /@ {_Real, _Complex}

{8, 8}

$\endgroup$
3
$\begingroup$

Using GroupBy:

MapAt[Length, GroupBy[a, Head], Outer[List, Range[2]]]
(*<|Real -> 8, Complex -> 8|>*)

Or, as pointed out, @Lukas Lang:

GroupBy[list, Head, Length]
(**<|Real -> 8, Complex -> 8|>**)
$\endgroup$
2
  • 1
    $\begingroup$ You can also use the third argument of GroupBy to do the counting for you: GroupBy[a, Head, Length] $\endgroup$
    – Lukas Lang
    Commented Sep 6, 2022 at 22:45
  • $\begingroup$ Thanks for pointing out that important detail, @Lukas Lang! :) $\endgroup$ Commented Sep 6, 2022 at 22:47
2
$\begingroup$
list = 
  {-7.61575, 7.5, -6.84206, 6.64598, 5.7654, -5.64823, 
   4.69842, -4.5, -1.86729 + 1.90939 I, -1.86729 - 1.90939 I, 
   0.905621 + 1.98443 I, 0.905621 - 1.98443 I, 0.631991 + 1.96227 I, 
   0.631991 - 1.96227 I, 0.327801 + 1.9312 I, 0.327801 - 1.9312 I};

Tally[Head /@ list]

{{Real, 8}, {Complex, 8}}

{#, Count[list, Blank[#]]} & /@ {Real, Complex}

{{Real, 8}, {Complex, 8}}

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