2015-06-16 1 views
1

Его вложенная карта с содержание, как это, когда я распечатать его на экранеКак разблокировать искру rdd, который имеет следующий тип ((String, scala.collection.immutable.Map [String, scala.collection.immutable.Map [String, Int]]))

(5, Map ("ABCD" -> Map("3200" -> 3, 
        "3350.800" -> 4, 
        "200.300" -> 3) 
(1, Map ("DEF" -> Map("1200" -> 32, 
         "1320.800" -> 4, 
         "2100" -> 3) 

мне нужно, чтобы получить что-то вроде этого

Case Class(5, ABCD 3200, 3) 
Case Class(5, ABCD 3350.800, 4) 
CaseClass(5,ABCD., 200.300, 3) 
CaseClass(1, DEF 1200, 32) 
CaseClass(1 DEF, 1320.800, 4) 

и т.д. и т.п. в основном список тематических классов

и отобразить его в случае класса, поэтому Я могу сохранить его в кассандре. Я пробовал делать flatMapValues, но это гнездо карты только на один уровень. Также используется flatMap. что это не работает или я ошибаюсь

Любые предложения?

+0

Ваш пример вывода не имеет смысла. Можете ли вы написать его как тип scala? Список (5, ABCD, 3200, 3) или что-то в этом роде. –

+0

Я хочу их как список классов case @ JustinPihony –

ответ

3

довольно просто, используя для-понимание и некоторый шаблон соответствия для destructure вещи:

val in = List((5, Map ("ABCD" -> Map("3200" -> 3, "3350.800" -> 4, "200.300" -> 3))), 
       (1, Map ("DEF" -> Map("1200" -> 32, "1320.800" -> 4, "2100" -> 3)))) 

case class Thing(a:Int, b:String, c:String, d:Int) 

for { (index, m) <- in 
     (k,v) <-m 
     (innerK, innerV) <- v} 
     yield Thing(index, k, innerK, innerV) 

//> res0: List[maps.maps2.Thing] = List(Thing(5,ABCD,3200,3), 
//          Thing(5,ABCD,3350.800,4), 
//          Thing(5,ABCD,200.300,3), 
//          Thing(1,DEF,1200,32), 
//          Thing(1,DEF,1320.800,4), 
//          Thing(1,DEF,2100,3)) 

Так давайте выберем часть для-понимания

(index, m) <- in 

Это то же самое, как

t <- in 
(index, m) = t 

В первой строке t последовательно будет установлено значение ea ch элемент in. Поэтому t является кортеж (Int, Map(...)) Паттен соответствия позволяет нам положить, что «Паттен» для кортежа на правой стороне и компилятор выбирает врозь кортеж, устанавливает index к Int и m на карте.

(k,v) <-m 

Как и раньше это эквивалентно

u <-m 
(k, v) = u 

И на этот раз u принимает каждый элемент карты. Которые снова являются кортежами ключа и значения. Таким образом, k устанавливается последовательно каждому ключу и v на значение.

И v ваша внутренняя карта поэтому мы делаем то же самое снова с внутренней картой

(innerK, innerV) <- v} 

Теперь у нас есть все, что нужно, чтобы создать класс дела. yield просто говорит, что делает сборник того, что «дается» каждый раз через цикл.

yield Thing(index, k, innerK, innerV) 

Под капотом, это просто приводит к набору карт/flatmaps

yield только значение Thing(index, k, innerK, innerV)

Мы получаем один из тех, для каждого элемента v

v.map{x=>val (innerK, innerV) = t;Thing(index, k, innerK, innerV)} 

, но есть внутренняя карта на элемент внешней карты

m.flatMap{y=>val (k, v) = y;v.map{x=>val (innerK, innerV) = t;Thing(index, k, innerK, innerV)}} 

(flatMap потому что мы получаем список списков, если мы просто сделали map, и мы хотим, чтобы сгладить его только список элементов)

Кроме того, мы делаем один из тех, для каждого элемента в списке

in.flatMap (z => val (index, m) = z; m.flatMap{y=>val (k, v) = y;v.map{x=>val (innerK, innerV) = t;Thing(index, k, innerK, innerV)}} 

Давайте сделаем это в _1, _2 стиль-у.

in.flatMap (z=> z._2.flatMap{y=>y._2.map{x=>;Thing(z._1, y._1, x._1, x._2)}}} 

, который производит точно такой же результат. Но разве это не понятно, как понимание?

+1

спасибо @Paul .... ваш ответ немного сложный для меня, чтобы понять .. вы можете объяснить немного больше о том, что происходит ... Я довольно новый для сопоставления scala/pattern, в частности –

+1

Вам не хватает некоторых полезных инструментов, если вы не знаете соответствия шаблонов, поэтому я рекомендую вам прочитать об этом. я добавлю объяснение –

+0

Я уверен ... прочитает @paul любые предложения для страниц блога, в которых участвуют примеры сопоставления шаблонов. Теперь ваш ответ имеет смысл. Спасибо за объяснение –

1

Вы можете сделать это, как это, если вы предпочитаете операции по сбору

case class Record(v1: Int, v2: String, v3: Double, v4: Int) 

    val data = List(
     (5, Map ("ABC" -> 
     Map(
      3200. -> 3, 
      3350.800 -> 4, 
      200.300 -> 3)) 
     ), 
     (1, Map ("DEF" -> 
     Map(
      1200. -> 32, 
      1320.800 -> 4, 
      2100. -> 3)) 
     ) 
    ) 

    val rdd = sc.parallelize(data) 

    val result = rdd.flatMap(p => { 
     p._2.toList 
     .flatMap(q => q._2.toList.map(l => (q._1, l))) 
     .map((p._1, _)) 
    }).map(p => Record(p._1, p._2._1, p._2._2._1, p._2._2._2)) 

    println(result.collect.toList) 
    //List(
    // Record(5,ABC,3200.0,3), 
    // Record(5,ABC,3350.8,4), 
    // Record(5,ABC,200.3,3), 
    // Record(1,DEF,1200.0,32), 
    // Record(1,DEF,1320.8,4), 
    // Record(1,DEF,2100.0,3) 
    //) 
+0

спасибо @ user52045 Я понял это из http://stackoverflow.com/questions/30080136/scala-spark-array-mapping час назад забыл написать ответ .... в любом случае спасибо, я делал именно то, то же самое . –

+0

Это может быть сокращено. Вам не нужно конвертировать Карты в списки перед их отображением. –

+0

Да, я тоже собирался указать на это. Оба ваши ответы правильные, но ответ Павла более читабельен после его объяснения. Спасибо @Paul –

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