Разбор CSV и добавление только совпадающих строк в список функционально в Scala - PullRequest
0 голосов
/ 28 марта 2020

Я читаю CSV scala. Человек - это дело класса

Case class Person(name, address)

    def getData(path:String,existingName) : List[Person] = {

      Source.fromFile(“my_file_path”).getLines.drop(1).map(l => {
        val data = l.split("|", -1).map(_.trim).toList
        val personName  = data(0)

        if(personName.equalsIgnoreCase(existingName)) {
          val address=data(1)
          Person(personName,address)
           //here I want to add to list

        }
        else
          Nil
       ///here return empty list of zero length


     }).toList()

}

Я хочу добиться этого функционально в scala.

Ответы [ 2 ]

1 голос
/ 28 марта 2020

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

 def getData(path:String, existingName: String) : List[Person] = {

    val source = Source.fromFile("my_file_path")
    val lst = source.getLines.drop(1).flatMap(l => {
      val data = l.split("|", -1).map(_.trim).toList
      val personName = data.head

      if (personName.equalsIgnoreCase(existingName)) {
        val address = data(1)
        Option(Person(personName, address))
      }
      else
        Option.empty
    }).toList

    source.close()

    lst
  }

мы читаем строку файла на строку, для каждого В строке мы извлекаем personName из первого поля csv, и если это то, что мы ищем, мы возвращаем (Option) Person, в противном случае - none (Option.empty). Делая flatmap, мы отбрасываем пустые опции (просто чтобы не использовать nils)

1 голос
/ 28 марта 2020

Вот базовый c подход к тому, что, я думаю, вы пытаетесь сделать.

case class Person(name:String, address:String)

def getData(path:String, existingName:String) :List[Person] = {
  val recordPattern = raw"\s*(?i)($existingName)\s*\|\s*(.*)".r.unanchored

  io.Source.fromFile(path).getLines.drop(1).collect {
    case recordPattern(name,addr) => Person(name, addr.trim)
  }.toList
}

Это не закрывает средство чтения файлов и не сообщает об ошибке, если файл не может быть открыт , что вы действительно должны сделать, но мы оставим это для другого дня.


update : добавлено закрытие файла и обработка ошибок через Using (Scala 2.13 )

import scala.util.{Using, Try}

case class Person(name:String, address:String)

def getData(path:String, existingName:String) :Try[List[Person]] =
  Using(io.Source.fromFile(path)){ file =>
    val recordPattern = raw"\s*(?i)($existingName)\s*\|\s*([^|]*)".r

    file.getLines.drop(1).collect {
      case recordPattern(name,addr) => Person(name, addr.trim)
    }.toList
  }

обновленное обновление

ОК. Вот версия, которая:

  • сообщает об ошибке, если файл не может быть открыт
  • закрывает файл после его открытия и читает
  • , игнорируя ненужные пробелы и кавычки
  • совместимы с компилятором до 2.13
import scala.util.Try

case class Person(name:String, address:String)

def getData(path:String, existingName:String) :List[Person] = {
  val recordPattern =
    raw"""[\s"]*(?i)($existingName)["\s]*\|[\s"]*([^"|]*)*.""".r

  val file = Try(io.Source.fromFile(path))
  val res = file.fold(
    err => {println(err); List.empty[Person]},
    _.getLines.drop(1).collect {
      case recordPattern(name,addr) => Person(name, addr.trim)
    }.toList)
  file.map(_.close)
  res
}

А вот как работает регулярное выражение:

  • [\s"]* могут быть пробелы или кавычки
  • (?i) при совпадении учитывается регистр
  • ($existingName) сопоставить и захватить эту строку (1-я группа захвата)
  • ["\s]* могут быть пробелы или кавычка отметки
  • \| там будет символ бара
  • [\s"]* там могут быть пробелы или кавычки
  • ([^"|]*) совпадать и захватывать все, что не указано или полоса
  • .* игнорировать все, что может появиться после
...