0

I am new to Scala. In the code below I am trying to return value from classing_summary function but I am facing trouble using the yield function. Here, I want to yield multiple values from inside the nested for loop.

Currently it does not return anything.

How to fix the code?

def classing_summary(arr: Array[(Double, Int)]) = {
      var value = 0.0
      var freq = 1
      var prevValue = Double.MinValue
      var bin = 1
      var classSize = 0.0
      var size = arr.length
      val tCount = arr.map{case (x,y) => y}.sum
      val output = for(i <- 0 until size) yield
      {
          value = arr(i)._1
          freq = arr(i)._2
          if(freq/tCount >= 0.05)
          { 
            for(j <- 0 until freq) yield
            {
              classSize += 1/tCount;
              (value,bin,classSize);
            }
            classSize = 0.0
            bin +=1
          }
          else
          {
            for(j <- 0 until freq ) yield
            {
              classSize += 1/tCount;
              (value,bin,classSize);
            }
            if(classSize >= 0.05)
            {
                 classSize = 0.0;
                 bin += 1;
            }
          }
      }
      output.toArray
    }

1 Answer 1

2

It doesn't return anything because your:

  if (classSize >= 0.05) {
     classSize = 0.0
     bin += 1
  }

doesn't return anything. Just save the value in advance:

  val r = for(j <- 0 until freq ) yield {
          classSize += 1/tCount;
          (value,bin,classSize);
  }

  if(classSize >= 0.05) {
        classSize = 0.0;
        bin += 1;
  }
  r

Your code (at least inside first for) could be optimized by the way:

  val r = for(j <- 0 until freq) yield {
      classSize += 1/tCount
      (value,bin,classSize)
  }

  if (freq/tCount >= 0.05 || classSize >= 0.05) {
      classSize = 0.0
      bin += 1;
  } 
  r

Even more:

  case class Data(value: Int = 0, bin: Boolean = 0, classSize: Int = 0, data: List[List[(Int, Int, Int)]])

  arr.foldLeft(Data()) {
      case ((value, freq), acc) =>
        val data = for(i <- 0 until freq) //generate data
          yield (value, bin, acc.classSize + i/tCount)

        val (bin, classSize) = //calculate new `bin` and `classSize`
          if (freq/tCount >= 0.05 || classSize >= 0.05)   
            (acc.bin + 1, classSize + freq / tCount)
          else (acc.bin, 0)

        Data(value, bin, classSize, acc.data :+ data) //accumulate
  } data
Sign up to request clarification or add additional context in comments.

2 Comments

@dk14...Thanks!!! seems to work now but the output returned from the function is not a cleaner one. Can the output be simplified so that I am able to write each yield output to a file. Thanks
@Kundan Kumar as I understand, your function was intended to return List[List[(Int, Int, Int)]] (my last one returns it by taking data from result). So If you want to print each list in a file just do for on it. If you want just List[(Int, Int, Int)] - then do .flatten on it (in my last one - you also may change data: List[List[(Int, Int, Int)]] to data: List[(Int, Int, Int)] and ++` instead of :+).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.