2015-06-11 4 views
0

Я пишу общие математические функции работы, которые работают с Spark RDD числовых значений.Scala - использовать математические операции на AnyVal

Для умножения, у меня есть что-то, что выглядит следующим образом:

def mult(rdd1: RDD[AnyVal], rdd2: RDD[AnyVal]): RDD[AnyVal] = { 
    rdd1.zip(rdd2).map(row => row._1 * row._2) 
} 

* не является членом AnyVal, так что это не компилируется. Есть ли что-то, что я могу сделать, чтобы сделать эту работу?

+0

Ну, если вы действительно уверены, что вы будете получать числовой тип и не может быть строка, то вы можете явно привести его '.asInstanceOf [NumericalTypeYouNeed]' , Излишне говорить, что это не рекомендуется, так как оно будет взорвано во время выполнения, если что-то еще придет, и я бы поставил под вопрос, почему «rdd1» и «rdd2'' AnyVal в первую очередь. –

+0

@AkosKrivachy Я использовал AnyVal, потому что RDD содержат числовые значения. Есть ли лучший способ получить эту функциональность? –

+0

Имеет ли 'rdd1' и' rdd2' один и тот же числовой тип? –

ответ

2

Как насчет использования Numeric для числовых типов?

это должно работать:

def mult[X:Numeric](rdd1: RDD[X], rdd2: RDD[X]): RDD[X] = { 
    import Numeric.Implicits._ 
    rdd1.zip(rdd2).map(row => row._1 * row._2) 
    } 

Если вы хотите быть в состоянии умножить ничего ни с чем, то вам необходимо сообщить компилятору, как это сделать.

Чтобы сделать это, давайте объявим черту, которая описывает функциональные возможности:

trait Multiplier[A, B, C] { 
    def multiply(a: A, b: B): C 
} 

Теперь вы можете определить обобщенную функцию умножения, поднимающий умножение на другие типы (я буду использовать Seq вы можете использовать RDD):

def multiply[A,B,C](as:Seq[A],bs:Seq[B])(implicit multiplier: Multiplier[A,B,C]): Seq[C] = 
    as zip bs map (p => multiplier.multiply(p._1, p._2)) 

Теперь давайте сказать компилятору, как Умножая Int с String (Scala может умножать String с Int, но . Не наоборот) Так что давайте определим множитель:

implicit object IntStringMultipler extends Multiplier[Int, String, Seq[String]] { 
    override def multiply(a: Int, b: String): Seq[String] = (1 to a) map (_ => b) 
} 

Чтобы сделать его более интересным, 2 * "x" будет Seq("x", "x") не "xx" как Scala собственного "x" * 2.

Теперь мы можем назвать: multiply(Seq(2, 3), Seq("a", "b")) получить List(Vector("a", "a"), Vector("b", "b", "b"))

+0

Прохладный ответ! Хотя я не думаю, что это решает основную проблему: 'AnyVal's :) –

+0

Действительно, это не так. Также я отметил слишком поздно rdd1 и rdd2 может разных типов. В любом случае компилятор должен знать, как размножать элементы RDD, поэтому необходимо будет использовать некоторые типы, которые имеют определенное умножение. Я попробую обновить мой ответ двумя типами. –

Смежные вопросы