在 Scala 中查找具有相同值的所有索引的更简洁方法

Cleaner way to find all indices of same value in Scala

我有一个这样的文本文件

NameOne,2,3,3
NameTwo,1,0,2

我想在 Scala 中找到每一行中最大值的索引。所以这个的输出将是

NameOne,1,2
NameTwo,2

我目前正在使用下面的函数来执行此操作,但我似乎找不到没有 for 循环的简单方法,我想知道是否有更好的方法。

def findIndices(movieRatings: String): (String) = {
    val tokens = movieRatings.split(",", -1)
    val movie = tokens(0)
    val ratings = tokens.slice(1, tokens.size)
    val max = ratings.max
    var indices = ArrayBuffer[Int]()

    for (i<-0 until ratings.length) {
        if (ratings(i) == max) {
            indices += (i+1)
        }
    }

    return movie + "," + indices.mkString(",")

}

这个函数是这样调用的:

val output = textFile.map(findIndices).saveAsTextFile(args(1))

刚开始学习 Scala,所以任何建议都会有所帮助!

您可以 zipWithIndex 并使用 filter:

ratings.zipWithIndex
  .filter { case(_, value) => value == max }
  .map { case(index, _) => index }

我注意到您的代码实际上并没有根据您的示例输入产生预期的结果。我将假设给出的示例是正确的结果。

def findIndices(movieRatings :String) :String = {
  val Array(movie, ratings @_*) = movieRatings.split(",", -1)
  val mx = ratings.maxOption  //Scala 2.13.x
  ratings.indices
         .filter(x => mx.contains(ratings(x)))
         .mkString(s"$movie,",",","")
}

请注意,这并没有解决您算法的一些缺点:

  • 电影名称中不允许有逗号。
  • 仅适用于 0 到 9 的评分。不允许有空格。

测试:

List("AA"
  ,"BB,"
  ,"CC,5"
  ,"DD,2,5"
  ,"EE,2,5, 9,11,5"
  ,"a,b,2,7").map(findIndices)

//res0: List[String] = List(AA,    <-no ratings
//                        , BB,0   <-comma, no ratings
//                        , CC,0   <-one rating
//                        , DD,1   <-two ratings
//                        , EE,1,4 <-" 9" and "11" under valued
//                        , a,0    <-comma in name error
//                        )