количество строк в списке, содержащемся в прочитанном файле - PullRequest
0 голосов
/ 20 февраля 2019

Я новичок в SO, но потратил дни на изучение вопросов.Ближайший связанный с этим вопрос, который я нашел, это Как сравнить каждое слово строки в файле с элементом списка в scala? , но это относится к 2014 году, так что теперь могут быть разные решения.

Также в приведенном выше сообщении лучший ответ использует изменяемую структуру данных, которую я стараюсь избегать.Последний ответ Димы выглядел более функциональным, но не сработал: (

Я пытаюсь создать аналогичную программу в SCALA, за исключением того, что вывод должен содержать общее количество ключевых слов и все ключевые слова должны быть выведены, дажеесли совпадений не найдено, то счетчик будет равен нулю.

Ключевые слова для проверки жестко закодированы в список, однако я также хочу добавить опцию второго предоставленного пользователем аргумента, который содержит ключевые слова.Пока я пришел к следующему, но получил отстой:

object FileAnalyser extends App {

val hardcodedkeywords = List("foo", "bar", "hello")

if (args.length > 1) {
  val keywords = args(1).toList
  try {
    val rdd = Source.fromFile(args(0)).getLines.toList.zipWithIndex.flatMap {
      case(line, index) => line.split("\\W+").map { (_, index+1) }
    } //.filter(keywords.contains(_)).groupBy { _._1 }.mapValues(_._2)
  } catch {
    case ioe: IOException => println(ioe)
    case fnf: FileNotFoundException => println(fnf)
    case _: Throwable => println("Uknown error occured")
  }
} else 
  try {
    val rdd = Source.fromFile(args(0)).getLines.toList.zipWithIndex.flatMap {
      case(line, index) => line.split("\\W+").map { (_, index+1) }
    } //filter(hardcodedkeywords.contains(_))
      //.groupBy { _._1 }.mapValues(_._2)
  } catch {
    case ioe: IOException => println(ioe)
    case fnf: FileNotFoundException => println(fnf)
    case _: Throwable => println("Uknown error occured")
  }
}

До сих пор мне удавалось использовать args (0), содержащий файл для чтения, для чтения и сопоставленный со списком, содержащим строку втакже строка + индекс + 1 (так как номера строк начинаются с 1, но индекс начинается с 0) Программа должна быть настолько функциональной, насколько это возможно, чтобы меньше изменяемых и изменяемых состояний и больше функций высшего порядка и рекурсий списка.

Спасибо Примервывод будет:

//alphabetical      //No duplicates
//order             //Increasing in no. 
keyword              lines                count
bar                  [1,2..]                6
foo                  [3,5]                  2
hello                []                     0

1 Ответ

0 голосов
/ 21 февраля 2019

Вот основные принципы того, как это можно сделать.

val keywords = List(/*key words here*/)

val resMap = io.Source
  .fromFile(/*file to read*/)
  .getLines()
  .zipWithIndex
  .foldLeft(Map.empty[String,Seq[Int]].withDefaultValue(Seq.empty[Int])){
    case (m, (line, idx)) =>
      val subMap = line.split("\\W+").toSeq  //separate the words
        .filter(keywords.contains)           //keep only key words
        .groupBy(identity)                   //make a Map w/ keyword as key
        .mapValues(_.map(_ => idx+1))        //and List of line numbers as value
        .withDefaultValue(Seq.empty[Int])
      keywords.map(kw => (kw, m(kw) ++ subMap(kw))).toMap
  }

//formatted results (needs work)
println("keyword\t\tlines\t\tcount")
keywords.sorted.foreach{kw =>
  println(kw + "\t\t" +
          resMap(kw).distinct.mkString("[",",","]") + "\t\t" +
          resMap(kw).length
         )
}

некоторые объяснения

  • io.Source - это библиотека (на самом деле object), которая предлагает несколько основных методов ввода / вывода, включая fromFile(), который открывает файл для чтения.
  • getLines() читает из файла одну строку вtime.
  • zipWithIndex присоединяет значение индекса к каждой прочитанной строке.
  • foldLeft() читает все строки файла, по одной за раз, и (в этом случае) создаетMap всех ключевых слов и их местоположений в строках.
  • resMap и subMap - это только имена, которые я выбрал для переменных, которые я строю.resMap (карта результатов) - это то, что создается после обработки всего файла.subMap - это промежуточная Карта, построенная из одной строки текста из файла.

Если вы хотите передать набор ключевых слов, я бы сделал это следующим образом:

val keywords = if (args.length > 1) args.tail.toList else hardcodedkeywords
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...