在 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
// )
我有一个这样的文本文件
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
// )