Присвоить вложенный продукт / кортеж массиву [Числовому]

#scala

#scala

Вопрос:

Я ищу быстрый способ присвоить продукт массиву с типом Numeric. Например, я хочу заполнить элементы массива значениями:

 // not restricted to be 4-by-2, can be abritary
// Double will be later replaced by type T : Numeric
var elements = new Array[Double](4*2) 
// can contain other Numemrics as Int
var values = ((11.0,12.0),(21.0,22.0),(31.0,32.0), (4.0,1.0)) 
  

Мой подход пока таков

 var i = 0;
var itRow = values.productIterator.asInstanceOf[Iterator[Product]]
while(itRow.hasNext){
    var itCol = itRow.next.productIterator.asInstanceOf[Iterator[Double]]
        while(itCol.hasNext){
            elements(i) = itCol.next.asInstanceOf[Double]
            i = i   1
        }
}
  

Это работает, если все записи в значениях двойные, но было бы неплохо, чтобы это работало и для произвольных чисел.
Во-вторых, есть ли более простой и быстрый способ сделать это? Возможно, было бы лучше сгладить кортеж с помощью

 def flatProduct(t: Product): Iterator[Any] = t.productIterator.flatMap {
    case p: Product => flatProduct(p)
    case x => Iterator(x)
}  

// edit: I think this is better, 
// but still the problematic if there are Int-types in values
flatProduct(values).asInstanceOf[Iterator[Dobule]].copyToArray(elements)
  

Что вы думаете?

Большое вам спасибо!

Ответ №1:

выбирайте сами:

 scala> values.productIterator.map{case (x: Double, y: Double) => Array(x, y)}.flatten.toList
res17: List[Double] = List(11.0, 12.0, 21.0, 22.0, 31.0, 32.0, 4.0, 1.0)

scala> values.productIterator.asInstanceOf[Iterator[(Double,Double)]].foldLeft(List[Double]()){(l, i) => i._2 :: i._1 :: l}.reverse
res18: List[Double] = List(11.0, 12.0, 21.0, 22.0, 31.0, 32.0, 4.0, 1.0)

scala> values.productIterator.foreach{var i = 0; {case (x: Double, y: Double) => elements(i) = x; elements(i   1) = y; i  = 2}}

scala> elements
res19: Array[Double] = Array(11.0, 12.0, 21.0, 22.0, 31.0, 32.0, 4.0, 1.0)
  

Комментарии:

1. Спасибо за быстрый ответ! Прошу прощения, что мое описание было недостаточно ясным. Проблема в том, что кортеж не ограничен размером 4 на 2 и не ограничен размером Double (но массив Double)

2. в этом случае ваш метод flatProduct хорош. просто добавьте .map(convert).toArray после его вызова, где convert это функция Any => Double . Поскольку это итератор, все выполняется за один проход (при преобразовании в массив)