已经有几天了,我开始在IntelliJ上学习Scala,我自己一个人学习。请承担我的菜鸟错误。我有一个超过10,000行和13列的csv文件。
列的标题为:
类别|评分|评论|尺寸安装|类型价格内容分级|类型|最后更新|当前版本Android版本
我确实设法通过以下代码读取并显示了csv文件:
import scala.io.Source
object task {
def main(args: Array[String]): Unit = {
for(line <- Source.fromFile("D:/data.csv"))
{
println(line)
}
}
}
此问题是此代码显示一个字母或数字,移至下一行并显示下一个字母或数字。它不会在一行中显示一行。
我想根据其分配的评论和评分优先级,找出每个类别(ART_AND_DESIGN,AUTO_AND_VEHICLES,BEAUTY…)的最佳应用。优先级分别定义为“审阅”列的60%和“评级”列的40%。通过使用这些分配的优先级值,为每个类别(ART_AND_DESIGN,AUTO_AND_VEHICLES,BEAUTY…)计算一个值。此值将帮助我们找到每个类别中最好的应用程序。您可以按如下方式使用优先级公式方程式。
优先级=((((rating / max_rating)* 100)* 0.4)+(((reviews / max_reviews)* 100)* 0.6))
此处max_rating是同一类别(如类别(“ ART_AND_DESIGN”))中给定数据的最高评分,最高评分为“ 4.7”,max_reviews是同一类别(如类别(“ ART_AND_DESIGN”))中应用的最高评价,最高评分为“ 295221” 。因此,类别(“ ART_AND_DESIGN”)的第一个数据记录的优先级值为:
评分= 4.1,评论= 159,
max_rating = 4.7,max_reviews = 295221
我的问题是,如何将每个列存储在数组中?这就是我计划计算数据的方式。如果还有其他方法可以解决上述问题,我欢迎您提出建议。
如果有人愿意,我可以上传一小部分数据。
答案 0 :(得分:3)
Source
默认为您提供一个字节Iterator
。要遍历行,请使用.getLines
:
Source.fromFile(fileName)
.getLines
.foreach(println)
要将行拆分为数组,请使用split
(假设列值不包含分隔符):
val arrays = Source.fromFile(fileName).getLines.map(_.split("|"))
最好避免使用原始数组。创建案例类可以编写更好,更易读的代码:
case class AppData(
category: String,
rating: Int,
reviews: Int,
size: Int,
installs: Int,
`type`: String,
price: Double,
contentRating: Int,
generes: Seq[String],
lastUpdated: Long,
version: String,
androidVersion: String
) {
def priority(maxRating: Int, maxReview: Int) =
if(maxRatings == 0 || maxReviews == 0) 0 else
(rating * 0.4 / maxRating + reviews * 0.6 /maxReview) * 100
}
object AppData {
def apply(str: String) = {
val fields = str.split("|")
assert(fields.length == 12)
AppData(
fields(0),
fields(1).toInt,
fields(2).toInt,
fields(3).toInt,
fields(4).toInt,
fields(5),
fields(6).toDouble,
fields(7).toInt,
fields(8).split(",").toSeq,
fields(9).toLong,
fields(10),
fields(11)
)
}
}
现在,您可以整齐地做自己想做的事情:
// Read the data, parse it and group by category
// This gives you a map of categories to a seq of apps
val byCategory = Source.fromFile(fileName)
.map(AppData)
.groupBy(_.category)
// Now, find out max ratings and reviews for each category
// This could be done even nicer with another case class and
// a monoid, but tuple/fold will do too
// It is tempting to use `.mapValues` here, but that's not a good idea
// because .mapValues is LAZY, it will recompute the max every time
// the value is accessed!
val maxes = byVategory.map { case (cat, data) =>
cat ->
data.foldLeft(0 -> 0) { case ((maxRatings, maxReviews), in) =>
(maxRatings max in.rating, maxReviews max in.reviews)
}
}.withDefault( _ => (0,0))
// And finally go through your categories, and find best for each,
// that's it!
val bestByCategory = byCategory.map { case(cat, apps) =>
cat -> apps.maxBy { _.priority.tupled(maxes(cat)) }
}