【问题标题】:How to compare each word of a line in a file with a list element in scala?如何将文件中一行的每个单词与scala中的列表元素进行比较?
【发布时间】:2019-03-31 18:48:58
【问题描述】:

我有一个包含纯文本的文件,如下所示: "Umbrella!! This is a very red umbrella. The umbrella should not be this red."

我正在从中提取所有关键字(在将所有单词转换为小写之后)并按字母顺序对它们进行排序,这给了我:

keywords = List(red, umbrella)

现在,我想逐行读取文件以找到包含“red”和“umbrella”这两个词的行号,即关键字列表中的词。

我知道如何逐行读取文件:

for(line <- Source.fromFile("file.txt").getLines())

但是,如何解析行中的每个单词并将其与列表元素进行比较?请帮忙!!

编辑:

我想要这样的输出:

red 2 3
umbrella 1 2 3

1 2 3 是行号。

【问题讨论】:

    标签: scala


    【解决方案1】:

    只需在每一行使用keywords.exists(line.contains) 并在需要时打印索引

    Source.fromFile("file.txt").getLines().zipWithIndex.foreach { 
        case(line, index) => 
            if (keywords.exists(line.contains)) println(index)
    }
    

    如果您不希望它区分大小写,只需 line.toLowerCase.contains

    Source.fromFile("file.txt").getLines().zipWithIndex.foreach { 
        case(line, index) => 
            if (keywords.exists(line.toLowerCase.contains)) println(index)
    }
    

    更新(以反映答案的变化)

    使输出类似于

    red 2 3
    umbrella 1 2 3
    

    让我们创建一个地图来存储每个单词的行号。

    var count = scala.collection.mutable.Map[String, List[Int]]()
    keywords.foreach { k => count += k -> List[Int]()}
    Source.fromFile("file.txt").getLines().zipWithIndex.foreach {
      case (line, index) =>
        keywords.foreach { w =>
          if (line.toLowerCase.contains(w)) 
            count(w) = count(w) :+ (index + 1)
        }
    }
    count.keys.foreach{ i => println(i + " " + count(i) )}
    

    要使输出与您指定的完全一致,请将最后一行替换为

      count.keys.foreach{ i =>  
                       print(i + " ") 
                          count(i).foreach{ j => print(j + " ") }
                          println()
                       }
    

    【讨论】:

    • 是否可以对文件中的所有单词使用toLowerCase,而不需要文件的内容,让所有单词在检查前都是小写的?
    • 是的,只要line.toLowerCase.contains
    • 但是,这只是给我输出 0 1 2 而我希望红色的输出为 1 2,伞的输出为 0 1 2。就像每个关键字分别一样。 :O
    • 这是错误的:List("foo", "bar").exists("foobar".contains) 返回true,但应该是falseList("foo", "bar", "baz").exists("foo".contains) 也返回 true 但应该为 false。
    【解决方案2】:

    您可以将每一行拆分为单词,然后检查列表是否包含所有关键字。使用 zipWithIndex 获取行号:

    Source.fromFile("file.txt").getLines().zipWithIndex.filter { case(line, index) => 
        val words = line.toLowerCase.split("\W")
        keywords.forall(words.contains)
    }
    .map(_._2)
    

    编辑:如果您想为每个关键字设置单独的索引,您需要先将 flatMap 映射到 (word,index) 元组列表中,然后再进行分组:

    Source.fromFile("file.txt").getLines().zipWithIndex
       .flatMap { case(line, index) => 
           line.toLowerCase.split("\W").map { (_, index+1) }  // "+1 because indexes are 0-based
       }
       .filter  { keywords.contains(_._1) }
       .groupBy { _._1 }.mapValues(_._2)
    

    这为您提供了一个 Map[String,List[Int]],其中键是关键字,值是出现给定关键字的行的索引列表。

    【讨论】:

      猜你喜欢
      • 2015-04-02
      • 1970-01-01
      • 2013-01-18
      • 2017-10-30
      • 1970-01-01
      • 2013-06-06
      • 2019-01-19
      • 2020-03-04
      • 2020-11-07
      相关资源
      最近更新 更多