在Scala里面如何使用元组

元组在Scala语言中是一种十分重要的数据结构,类似数据库里面的一行记录(row),它可以将不同类型的值组合成一个对象,在实际应用中十分广泛。


先来看一个简单的tuple定义:
````
val tuple=("张三",25)//定义一个tuple
val (name,age)=("张三",25)//变量绑定模式
````
上面的第二种例子中,可以直接通过name和age来访问单个tuple的元素

例子(1):

一个简单的模式匹配
````
val tuple=(1,2,3,4)

def tupleMatch(x:Any)=x match {
case (first,second)=> println(s"第一个元素:${first} 第二个元素:${second}")
case (first,_,three,_)=> println(s"第一个元素:${first} 第三个元素:${three}")
case _=> println("没有任何匹配")
}

tupleMatch(tuple)//匹配上面的第二个
````
例子(2):

根据类型匹配
````
def typeMatch(x:Any)=x match {

case x:String=> println("string")
case x:Int=> println("int")
case x:Boolean=>println("boolean")
case _=> println("其他")

}

typeMatch("x")
````
注意上面的代码里面case后面的如果有List[String]类型的,最好用一个类封装起来在做匹配,否则会出错。具体的方式请参考:
[url]https://www.cakesolutions.net/teamblogs/ways-to-pattern-match-generic-types-in-scala[/url]

例子(3):

变量绑定模式
````
//定义一个对象元组
case class Dog(val name:String,val age:Int)
val dog=Dog("Pet",2)

def patternMatch(x:Any)=x match {
case d@Dog(_,_)=>println("变量值:"+d.name)
case _=> println("默认")
}

patternMatch(dog)//Pet
````
注意普通的类不能直接使用上面的模式匹配

例子(4):

for循环的使用元组进行的模式匹配

````
val map= Map("java"->"Hadoop","js"->"vue","scala"->"spark")
//1,变量模式匹配
for( (k,v)<-map ){
println(k,v)
}

println("====================")
//2,常量模式匹配,第二个值必须是spark,才会打印出来
for( (k,e@"spark")<-map ){
println(k,e)
}
println("====================")
//3,类型匹配模式,注意elasticsearch是不会被打印出来的
for( (k,v:String)<- Map("java"->"Hadoop","js"->"vue","scala"->"spark", "elasticsearch"->"java".size) ){
println(k,v)
}
println("====================")
//4,构造函数模式匹配
case class Dog(val name:String,val age:Int)

for(Dog(name,age)<-List(Dog("pet",2),Dog("penny",3),Dog("digo",4) ) ){
println(s"Dog ${name} is ${age} years old")
}

println("====================")
//5,序列模式匹配
for( List(first,_*)<- List( List(1,2,3),List(4,5,6,7) ) ){

println(s"${first}")
}
println("====================")
//6,变量绑定的另一种模式
val list2=List( List(1,2,3),List(4,5,6,7))

def list2Match(x:AnyRef)=x match {

case List(first,e@List(4,_*)) => println(e)
case _=> println("defalult")
}
list2Match(list2)
````
结果:
````
(java,Hadoop)
(js,vue)
(scala,spark)
====================
(scala,spark)
====================
(java,Hadoop)
(js,vue)
(scala,spark)
====================
Dog pet is 2 years old
Dog penny is 3 years old
Dog digo is 4 years old
====================
1
4
====================
List(4, 5, 6, 7)
````



最后我们使用元组,来模拟一个类似下面的SQL的例子:

表(pet)结构:
````
name(string),ct(int)
cat,2
cat,6
cat,2
dog,1
dog,2

````
统计语句:
````
select name ,sum(ct) as c,count(*),max(ct),min(ct) from pet group by name order by c desc
````

Scala代码如下:
````

val list = ArrayBuffer[(String, Int)]()

list += (("cat", 2))
list += (("cat", 6))
list += (("cat", 2))
list += (("dog", 1))
list += (("dog", 2))


println("宠物名,数量")
//使用打印所有的数据
for ((name, count) <- list) {
println(name, count)

}

println("=================================")

//求出,按宠物名分组,出现数量和,出现总次数,最大数量,最小数量,并按照总次数降序排序
val result = list.groupBy(_._1).map {
case (key,valueList) => {
val sum = valueList.map(_._2).sum//求valueList出现次数的总和
val maxCount = valueList.max._2//最大次数
val minCount = valueList.min._2//最小次数
(key -> (sum, valueList.size, maxCount, minCount))//以Map的结果返回
}

}.toSeq.sortWith(_._2._1 > _._2._1)
//转化成Seq后才能进行排序操作,相当于取的是_._2代表的是value的值,
//继续_1代表的是取里面的sum进行降序排序,如果是<号,则是升序排


//使用元组遍历最终结果
println("宠物名,出现数量和,出现总次数,最大数量,最小数量")
for( (name,(sum,size,maxCount,minCount)) <-result ){
println(name,sum,size,maxCount,minCount)
}
````


其实,核心代码只有中间的这一部分:
````
val result = list.groupBy(_._1).map {//分组处理
case (key,valueList) => {
val sum = valueList.map(_._2).sum//求valueList出现次数的总和
val maxCount = valueList.max._2//最大次数
val minCount = valueList.min._2//最小次数
(key -> (sum, valueList.size, maxCount, minCount))//以Map的结果返回
}

}.toSeq.sortWith(_._2._1 > _._2._1)//降序排
````


最终结果:
````
宠物名,数量
(cat,2)
(cat,6)
(cat,2)
(dog,1)
(dog,2)
=================================
宠物名,出现数量和,出现总次数,最大数量,最小数量
(cat,10,3,6,2)
(dog,3,2,2,1)

````



简单解释一下核心部分的代码含义:

首先执行了一个groupBy函数,对元组里面的第一个元素也就是宠物名进行
分组,分组之后,每个宠物名一样的数据会聚合在一起,然后执行一个map函数,对里面的valueList进行各种运算,得出来我们
需要的结果后,最终再以Map的数据结构返回,因为Map本身是没法排序的,所以我们得先需要转成Seq类型,最后再执行sortWith方法对value里面的最大次数进行降序排,如果是升序排,只需要把大于号该成小于号即可。

总结:

本篇主要介绍了tuple几种常见的应用场景,通过使用tuple数据结构配合上scala强大的函数方法,我们可以轻松愉快的处理的各种数据集,感兴趣的小伙伴可以自己尝试一下。


[b][color=green][size=large] 有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。 技术债不能欠,健康债更不能欠, 求道之路,与君同行。 [/size][/color][/b] [img]http://dl2.iteye.com/upload/attachment/0104/9948/3214000f-5633-3c17-a3d7-83ebda9aebff.jpg[/img]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值