7

I have a list of associations keyed by real and imaginary numbers, like so:

matrix = {
   {<|"r" -> 0.368252, "i" -> 0.0199587|>, 
    <|"r" -> -0.461644, "i" -> 0.109868|>, 
    <|"r" -> -0.216081, "i" -> 0.562557|>, 
    <|"r" -> -0.479881, "i" -> -0.212978|>}, 

   {<|"r" -> 0.105028, "i" -> 0.632264|>, 
    <|"r" -> 0.116589, "i" -> -0.490063|>, 
    <|"r" -> 0.463378, "i" -> 0.231656|>,
    <|"r" -> -0.148665, "i" -> 0.212065|>},

   {<|"r" -> 0.463253, "i" -> 0.201161|>,
    <|"r" -> 0.460547, "i" -> 0.397829|>,
    <|"r" -> 0.222257, "i" -> 0.0129121|>,
    <|"r" -> 0.168641, "i" -> -0.544568|>},

   {<|"r" -> 0.255221, "i" -> -0.364687|>,
    <|"r" -> 0.191895, "i" -> -0.337437|>,
    <|"r" -> -0.12278, "i" -> 0.551195|>,
    <|"r" -> 0.560485, "i" -> 0.134702|>}
}

Given this, I can write

testmatrix = Join[Values[matrix], 2]`

to get a matrix, but it is a matrix of tuples. How can I get the complex number defined in each <|r -> Re[z], i -> Im[z]|> rather than the tuples?

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
MKF
  • 591
  • 2
  • 10

3 Answers3

10
Join[Values[matrix], 2].{1, I}

As J.M. pointed out, this can even be shortened to the following:

Values[matrix].{1, I}

A nice feature of this approach is that it produces packed arrays when possible.

J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
Henrik Schumacher
  • 106,770
  • 7
  • 179
  • 309
9
Apply[Complex, matrix, {2}] (* or *)
Map[{#r, #i}.{1, I} &, matrix, {2}]

{{0.368252 +0.0199587 I,-0.461644+0.109868 I,-0.216081+0.562557 I,-0.479881-0.212978 I},
{0.105028 +0.632264 I,0.116589 -0.490063 I,0.463378 +0.231656 I,-0.148665+0.212065 I},
{0.463253 +0.201161 I,0.460547 +0.397829 I,0.222257 +0.0129121 I,0.168641 -0.544568 I},
{0.255221 -0.364687 I,0.191895 -0.337437 I,-0.12278+0.551195 I,0.560485 +0.134702 I}}

kglr
  • 394,356
  • 18
  • 477
  • 896
5

I'm a bit uncomfortable with both @HenrikSchumacher's and @kglr's (first) answers, as they rely on the correct sorting order of the keys in the Associations: they assume that every matrix element is precisely of the form of an association with first the "r" part and second the "i" part.

Without relying on the sorting order, or on the presence of both elements, and making more use of the essential features of associations, we can do

matrix /. a_Association :> Lookup[a, {"r", "i"}, 0].{1, I}

This solution works even if one matrix element is of the form <|"r" -> 2|> or <|"i" -> -3|> (it will default the other coordinate to zero). It also works if the order of the elements is interchanged: <|"r" -> 2, "i" -> -3|> gives the same result as <|"i" -> -3, "r" -> 2|>. It also works on higher-dimensional tensors or ragged structures.

Roman
  • 47,322
  • 2
  • 55
  • 121