在Scala中提取域后缀和计算命中数

在Scala中提取域后缀和计算命中数,scala,Scala,寻找一些在vanilla Scala中优化此解决方案的建议,以解决我在教科书中遇到的问题: 假设您获得了如下数据: val计数=数组( “900,google.com”, “60,mail.yahoo.com”, “40,sports.yahoo.com”, “50,mobile.sports.yahoo.com”, “3,en.wikipedia.org” ) 第一个值表示该域收到的命中数。我想做的是能够汇总每个域和属于它的每个子域的计数。因此,输出应该如下所示: res=List( (“

寻找一些在vanilla Scala中优化此解决方案的建议,以解决我在教科书中遇到的问题:

假设您获得了如下数据:


val计数=数组(
“900,google.com”,
“60,mail.yahoo.com”,
“40,sports.yahoo.com”,
“50,mobile.sports.yahoo.com”,
“3,en.wikipedia.org”
)
第一个值表示该域收到的命中数。我想做的是能够汇总每个域和属于它的每个子域的计数。因此,输出应该如下所示:

res=List(
(“com”,1050),
(“google.com”,900),
(“yahoo.com”,150),
(“sports.yahoo.com”,90),
(“mail.yahoo.com”,60),
(“mobile.sports.yahoo.com”,50),
(“sports.yahoo.com”,40),
(“组织”,3),
(“en.wikipedia.org”,3)
)
以下代码至少在提供的数据上起作用:

对象解决方案{
val计数=数组(
“900,google.com”,
“60,mail.yahoo.com”,
“10,mobile.sports.yahoo.com”,
“40,sports.yahoo.com”,
“10,stackoverflow.com”,
“2,en.wikipedia.org”,
“1,es.wikipedia.org”,
“1、移动。运动”
)
case类DomainMapEntry(计数:Int,后缀:String)
私有后缀(str:String):列表[String]=
str.split('.').foldLeft(List.empty[String]){(acc,part)=>
零件::acc.map(rest=>s“$rest.$part”)
}
//拆分数组中的每个条目,提取后缀并与count配对。
私有def createDomainMap(str:String):列表[选项[DomainMapEntry]]=
str.split(“,”).take(2).列表匹配{
案例h::t::Nil=>extractSuffix(t).map(后缀=>Some(DomainMapEntry(Integer.parseInt(h),后缀)))
案例=>列表(无)
}
//创建后缀和计数的地图,按后缀展平和分组,
//对分组计数求和,并按相反顺序排序
def解析计数(arr:Array[String])=
啊
.map(createDomainMap)
压平
压平
.groupBy(\后缀)
.mapValues(0.map(0.count).sum)
托利斯先生
.sortBy(-uuu.u 2)
def main(args:Array[String]):Unit=println(parseCounts(counts).mkString(“\n”))
}
但是,我觉得它可以大大改进。显然,
case类
可能只是一个元组,但在算法上,我觉得我遗漏了一些东西,而且我也不太担心格式错误的数据,只是一个练习

  • 我能更优雅地(简单地说,性能更好)提取带有计数的后缀吗

  • 那双
    flatten
    电话,可能是一股代码气味

  • 拆分和重新连接以创建后缀模式似乎很简单


  • 有许多不同的方法来完成这样的任务。这里有一个选择

    counts.flatMap{str=>
    val数组(num,domain)=str.split(“,”)
    域。拆分(“\\”)
    .尾巴
    .collect{如果d.nonEmpty=>(d.mkString(“.”,num.toInt)}
    }.groupMapReduce(u._1)(u._2)(u+)//Scala 2.13.0
    托利斯先生
    .sortBy(-uuu.u 2)
    //res0:List[(String,Int)]=List((com,1050)
    //,(谷歌网站,900)
    //,(yahoo.com,150)
    //,(sports.yahoo.com,90)
    //,(mail.yahoo.com,60)
    //,(mobile.sports.yahoo.com,50)
    //,(wikipedia.org,3)
    //,(组织,3)
    //,(en.wikipedia.org,3))
    

    请注意,这不会筛选错误输入,因此必须事先添加或完成。

    谢谢,很高兴我这么问。我从您的提交中学到了三件事,scala的模式匹配在case语句之外工作
    tails
    ,以及关于2.13
    groupMapReduce
    的另一件很酷的事情,这应该有助于解决
    mapValues
    可能存在的一些奇怪之处。干杯