Home > Net >  How foldLeft works with Seq of tupels?
How foldLeft works with Seq of tupels?

Time:07-28

I'm new in Scala, so struggling to understand Syntax. Please check below code.

def myDef(entityMap: Seq[(DataName.Value, DataFrame)]) : Seq[Map[Int,Info]] = {

    val depenInfo = Seq[Map[Int,Info]]()

    entityMap.foldLeft(depenInfo)((info,entity) => {
    val(dataName: DataName.Value, df: DataFrame) = entity
    info    df.createDepenInfo(dataName)    
 })
}

what am I getting is, Seq of tuples having to two types (DataName.Value, DataFrame) and return type of myDef is Seq of Map.

After that, create one empty Seq of Map, then feed this empty Map to entityMap.foldLeft so that it could add more values in it.

Remaining part I kind of literally stuck to understand. Can anyone please help me to understand what's happening ? If possible with any very simple example similar to above with output.

Thanks

CodePudding user response:

Since there are many user defined class I don't know, I try to mock your data type as following:

import scala.collection.{immutable, Seq}

object Example {

  object DataName {
    type Value = Int
  }

  case class DataFrame(fakeData: String) {
    def createDepenInfo(value: DataName.Value): Seq[Map[Int, Info]] = Seq(Map(value -> fakeData))
  }

  type Info = String

  def myDef(entityMap: Seq[(DataName.Value, DataFrame)]): Seq[Map[Int, Info]] = {

    val depenInfo = Seq[Map[Int, Info]]()

    entityMap.foldLeft(depenInfo)((info: Seq[Map[Int, Info]], entity: (DataName.Value, DataFrame)) => {
      // here is Pattern matching on tuples,
      // here we extract (dataName: DataName.Value, df: DataFrame) from tuple entity: (DataName.Value, DataFrame)
      // see: https://docs.scala-lang.org/tour/tuples.html
      val (dataName: DataName.Value, df: DataFrame) = entity

      //    is a method of Seq, it contact two Seq to one
      // e.g. Seq(1,2,3)    Seq(4,5,6) = Seq(1,2,3,4,5,6)
      info    df.createDepenInfo(dataName)

    })
  }

  def main(args: Array[String]): Unit = {
    val data: immutable.Seq[(DataName.Value, DataFrame)] = (1 to 5).map(i => (i, DataFrame((i   'a').toChar.toString)))

    // Vector((1,DataFrame(b)), (2,DataFrame(c)), (3,DataFrame(d)), (4,DataFrame(e)), (5,DataFrame(f)))
    println(data)

    val res = myDef(data)

    // List(Map(1 -> b), Map(2 -> c), Map(3 -> d), Map(4 -> e), Map(5 -> f))
    println(res)
  }

}

raw data: Vector((1,DataFrame(b)), (2,DataFrame(c)), (3,DataFrame(d)), (4,DataFrame(e)), (5,DataFrame(f)))

let's say info df.createDepenInfo(dataName) is result

  1. info = Seq(), entity = (1,DataFrame(b)), reuslt=Seq(Map(1 -> b))
  2. info = Seq(Map(1 -> b)), entity = (2,DataFrame(c)), result=Seq(Map(1 -> b), Map(2 -> c))
  3. info = Seq(Map(1 -> b), Map(2 -> c)), entity = (3,DataFrame(d)), result=Seq(Map(1 -> b), Map(2 -> c), Map(3 -> d))

and so on...

You see, during each caluclation, the value info is "saved"(with a init value from deepInfo), and the entity value is "read" from entityMap.

So the final result is List(Map(1 -> b), Map(2 -> c), Map(3 -> d), Map(4 -> e), Map(5 -> f))

CodePudding user response:

In your code, info is the accumulator, depenInfo is the initial value, and entity is a map item (i.e. a key-value tuple). Here's a simpler example where acc is the accumulator and kv is the key-value pair being "read" from the map.

Map(1->2).foldLeft(0)((acc, kv) => {
  val (k, v) = kv;
  println(s"$k, $v, $acc");
  acc   k   v
})
// prints: 1, 2, 0
// result: 3

To read about the accumulator pattern: https://www.arothuis.nl/posts/accumulators-and-folds/

As for the , that is the operator/method in Seq (sequence) which concatenates this sequence to another sequence. Simple example with concatenating length 1 sequences together:

Seq(1)    Seq(2)
// Seq(1, 2)
  • Related