(Scalding) groupBy foldLeft с помощью группировки по значению в фолде

Имейте такие данные, как:

pid  recom-pid
1   1
1   2
1   3
2   1
2   2
2   4
2   5

Нужно сделать:

pid, recommendations
1    2,3
2    1,4,5

Это означает игнорировать себя из 2-го столбца и вводить остальные в строку, разделенную запятыми. Его данные, разделенные табуляцией

Пробовал варианты, но не уверен, как ссылаться на productId в foldLeft

.groupBy('productId) {     
  _.foldLeft(('prodReco) -> 'prodsR)("") {
    (s: String, s2: String) =>
      {
        println(" s " + s + ", s2 :" + s2 + "; pid :" + productId + ".")
        if (productId.equals(s2)) {
          s
        } else {
          s + "," + s2;
        }
      }
  }
}

Использование scala 2.10 с scalding 0.10.0 и cascading 2.5.3. Нужен обжигающий ответ. Я знаю, как манипулировать данными в scala. Мне просто интересно, как получить столбцы во время группы с помощью ошпаривания и использовать их для условного сгиба влево или других средств для получения отфильтрованного вывода.

Полный рабочий пример см. на странице https://github.com/tgkprog/scaldingEx2/tree/master/Q1


person tgkprog    schedule 04.10.2015    source источник
comment
почему бы не использовать фильтр для удаления собственных пар, а затем группировать по идентификатору?   -  person roterl    schedule 05.10.2015
comment
Да, это работает, просто хотел что-то в scalding groupBy, чтобы можно было отфильтровать в той же фазе.   -  person tgkprog    schedule 07.10.2015


Ответы (4)


Вместо groupBy, а затем foldLeft используйте только foldLeft.
Вот решение, использующее коллекции scala, но оно должно работать с использованием а также масштабирование:

val source = List((1,1), (1,2), (1,3), (2,1), (2,2), (2,4), (2,5))                                                                                
source.foldLeft(Map[Int, List[Int]]())((m,e) =>                                
  if (e._1 == e._2) m else m + (e._1 -> (e._2 :: m.getOrElse(e._1, List()))))  
person roterl    schedule 11.10.2015
comment
foldLeft не является членом Pipe. Похоже, в документах он есть как заголовок, но находится под редуктором. - person tgkprog; 26.10.2015

Просто groupBy и map должно быть достаточно, чтобы выполнить то, что вы хотите.

// Input data formatted as a list of tuples.
val tt = Seq((1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 4), (2, 5))

tt
  .groupBy(_._1) // Map(2 -> List((2, 1), ...), 1 -> List((1, 1), ...))
  .toSeq // for easier mapping
  .map({
    case (pid, recomPids) => {
      val pids = recomPids.collect({
        case recomPid if recomPid._2 != pid => recomPid._2
      })
      (pid, pids)
     }
   }) // List((2, List(1, 4, 5)), (1, List(2, 3)))

Я упростил форму ввода/вывода, чтобы сосредоточиться на приведении коллекций в правильную форму.

person Gavin Schulz    schedule 05.10.2015
comment
Красиво, но не юзабельно. Мне нужно решение в scalding api. - person tgkprog; 07.10.2015

Предположим pid| recom-pid > temp.txt и так далее

import scala.io.Source
val xs = Source.fromFile("temp.txt").getLines.toArray.map(_.split("\\|"))

Мы конвертируем xs в кортежи, вот так

val pairs = for (Array(pid, recom) <- xs) yield (pid,recom)
Array((1,1), (1,2), (1,3), (2,1), (2,2), (2,4), (2,5))

и сгруппировать по первому элементу,

val g = pairs.groupBy(_._1)
Map(2 -> Array((2,1), (2,2), (2,4), (2,5)), 1 -> Array((1,1), (1,2), (1,3)))

Затем мы удаляем сопоставленные кортежи identity, что гарантирует наличие записи в карте, где пустой массив означает, что был только кортеж идентификатора (а именно, уникальное вхождение 3|3 приведет к 3 -> Array()),

val res = g.mapValues(_.filter { case (a,b) => a != b } )
Map(2 -> Array((2,1), (2,4), (2,5)), 1 -> Array((1,2), (1,3)))
person elm    schedule 05.10.2015
comment
Красиво, но не юзабельно. Мне нужно решение в scalding api. - person tgkprog; 07.10.2015

Предполагая, что ваш ввод строки правильный, который возвращает вам Map[String, Array[String]]

s.split('\n')
.map(_.split("\\|"))
.groupBy(_(0))
.mapValues(_.flatten)
.transform {case (k, v) ⇒ v.filter(_ != k)}
person I See Voices    schedule 05.10.2015