список возврата цикла scala foreach - PullRequest
0 голосов
/ 01 ноября 2019

Я новичок в Scala (и функциональное программирование, в основном). Я пытаюсь перебрать список строк (можно представить как строки), где каждая строка будет передана в другой метод scala, где я делаю некоторые манипуляции с входной строкой, а затем возвращаю строку в цикл for.

ниже не рабочий код, но это то, что я ожидаю работать.

     val input_list = spark.read
          .format("com.crealytics.spark.excel")
          .option("sheetName" , "SchemaInfo")
          .option("useHeader", "true")
          .schema(profilerSchema)
          .load(path)  // this is spark dataframe, which has rows.

 val columnNames : List[String] = new List("Hello" , "world");

         var outputList = new ListBuffer[String]();

        // Here i am iterating the input_list where i pass each ele to getString() method where  
        // it returns the final string which i want to add to outputList. 

         input_list.foreach(i => {
                val res: String = getString(row, columnNames)
                 outputList += res;
               }));


         def getString(row: Row, schemaNames: List[String]) : String  = {

        // some implementation where it returns a string.
        }

Ниже приведено сообщение об ошибке, которое я получаю (откажитесь от номера строки. Это происходит в цикле foreach.).

Error:(57, 14) overloaded method value foreach with alternatives:
  (func: org.apache.spark.api.java.function.ForeachFunction[org.apache.spark.sql.Row])Unit <and>
  (f: org.apache.spark.sql.Row => Unit)Unit
 cannot be applied to (org.apache.spark.sql.Row => scala.collection.mutable.ListBuffer[String])
    excel_df.foreach{row => (jsonStrList += convertRowToJSON(row, columnNames))};

Мне трудно писать логику,любая помощь очень ценится.

1 Ответ

2 голосов
/ 01 ноября 2019
input_list.foreach(i => {
      val res: String = getString(row, columnNames)
       outputList += res;
     });

Ваша функция внутри метода foreach возвращает значение outputList. Если вы посмотрите на подпись, возвращаемое значение должно быть Unit - это означает, что метод не возвращает значение. Предполагается, что вы делаете некоторые вычисления, которые ничего не возвращают.

Вы должны использовать карту вместо foreach. Вам не нужен foreach и переменная outputList.

input_list.map(row => {
       // Logic to return the item that you want to compute
     })
     .toList()

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

Пример:

List(1,2,3,4,5,6,7,8,9,10)
// filter gives you the list of even numbers between 1 and 10
.filter(i => i % 2 == 0) 
// This gives you the squares of the even numbers between 1 and 10
.map(i => i * i)
// This gives the doubles of the squares of the even numbers
.map(i => i * 2)

Вы также можете сделать это:

val evenNumbers = List(1,2,3,4,5,6,7,8,9,10)
// filter gives you the list of even numbers between 1 and 10
.filter(i => i % 2 == 0) 

val squares= evenNumbers
// This gives you the squares of the even numbers between 1 and 10
.map(i => i * i)

val doubleSquares = squares
// This gives the doubles of the squares of the even numbers
.map(i => i * 2)

// this will return a tuple with lists when it's the last statement in a function or method.
(squares, doubleSquares)

Как видите, объекты ListBuffer не объявлены. Пример немного надуманный, вы можете объединить последние две карты в одну, но я хотел доказать свою точку зрения. Вы можете выполнять другие операции, группировать элементы, сортировать их и т. Д.

Вам нужно больше узнать о scala и FP в целом. Это хорошее введение: https://docs.scala -lang.org / Overviews / scala-book / ввод.html и это: https://docs.scala -lang.org / обзоры / scala-book / Passing-functions-around.html .

Вы также можете попробовать что-то здесь в браузере: https://scastie.scala -lang.org .

...