1

I have the following normalization function:

...
private def NormalizeValues(dataValues: Array [Double]): Array[Double] = {
val min = dataValues.min
val max = dataValues.max
dataValues.map(v => (v - min) / (max - min))
}
...

And I want it to work whether it receives an Array of Double or an Array of Int. Better than just turning the Array of Int to Array of Double, I guess there must be a better way to do this maybe using a more generic type or specifying that Array[Doubles] and Array[Int] can be received indistinctly, in the function definition.

Do you have any idea?

Cristina HG
  • 660
  • 5
  • 15
  • Do you want to use `Int`'s `/` for that case? I suspect not... – Alexey Romanov Sep 02 '18 at 16:23
  • What's supposed to happen with `[0, 1, 3]`? `min = 0`, `max = 3`, `(1 - 0) / (3 - 0) = 1/3`. It's not an integer. Do you want to round it, or `floor` it, or `ceil` it, or do sth. else? Integers are not a [field](https://en.wikipedia.org/wiki/Field_(mathematics)), and therefore there is no good superclass / typeclass / interface shared by `Double`s and `Int`s. – Andrey Tyukin Sep 02 '18 at 16:24
  • That is just a function part of a class part of an preprocessing algorithm. Don't you worry about the indeterminations case, NaN values are treated inside the algorithm :) – Cristina HG Sep 02 '18 at 16:29
  • There are two slightly different questions in your title and in the text. In the title, you ask about an "array of either Int or Double" (i.e. something like `Array[Int | Double]`) whereas in the text you ask about "an Array of Double or an Array of Int" (i.e. something like `Array[Int] | Array[Double]`). [Note that those are actually legal types in Dotty and thus likely also in Scala 3.] – Jörg W Mittag Sep 02 '18 at 17:40
  • 1
    For implementing this idea in Scala, see the awesome answers to this [tag:scala] question on [so]: https://stackoverflow.com/q/3508077/2988 – Jörg W Mittag Sep 02 '18 at 17:47

1 Answers1

3

Here is a version that converts all inputs to Double, and then proceeds exactly as your original code:

def normalize[N: math.Numeric](data: Array[N]): Array[Double] = {
  val num = implicitly[Numeric[N]]
  val dataValues = data.map(num.toDouble)
  val min = dataValues.min
  val max = dataValues.max
  dataValues.map(v => (v - min) / (max - min))
}

The return type is always Array[Double], because it does not seem to make any sense to return Array[N] for Ints, Longs, and all other integer types.

An example:

normalize(Array[Int](0, 1, 3))
// returns: Array[Double]
// Array(0.0, 0.3333333333333333, 1.0)
Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93