Scala 集合常用函数

news2024/11/16 16:22:09

文章目录

  • 集合常用函数
    • 一、基本属性和常用操作
      • 1、常用方法
      • 2、案例示例
    • 二、衍生集合
      • 1、衍生集合常用方法操作
      • 2、案例示例
    • 三、集合简单计算函数
      • 1、常用计算操作
      • 2、案例示例
    • 四、集合计算高级函数
      • 1、语义说明
      • 2、案例示例

集合常用函数

一、基本属性和常用操作

1、常用方法

(1) 获取集合长度
(2) 获取集合大小
(3) 循环遍历
(4) 迭代器
(5) 生成字符串
(6) 是否包含
注意这些是集合类型的通用操作

2、案例示例

总结:获取集合的长度使用lenght方法,对于线性的序列都可以用lenght方法来获取长度,但是像那种无序的集合,像Set集合,就不能用lenght方法,可以用size方法,来获取大小。遍历的话可以用for循环,获取迭代器。或者foreach方法都可以。生成字符串,使用mkstring()方法,这个方法非常好用。判断这个元素在集合中是否包含,使用contains()方法,如果存在返回true,如果不存在返回false

package Scala03_shujujiegou
//这些是集合类型的通用的一些常用操作
class test11_tongyong {

}
object test11_tongyong{
  def main(args: Array[String]): Unit = {
    val list = List(6,9,6,89,99) //熟悉的列表
    val set = Set(6,8,6,1) //Set集合,不关心这个有多长因为他根本是无序的,所以关心的是他的大小
      //(1) 获取集合长度
    println(list.length) //获取长度length方法,只要是线性的序列都可以用lenght方法,如果是那种无序的可以用size
    //println(set.lenght) //对于某一些类型而言是没有lenght这个属性的,比如Set集合
    println(set.size) //对于无序的用大小比较合适,
    println("================")
      //(2) 获取集合大小
    println(list.size) //获取大小size方法
      //(3) 循环遍历
    for (i <- list){
      println(i)
    }
    for (i <- 0 until list.length){
      println(list(i))
    }

    println("============")
      //(4) 迭代器
    val iter = list.iterator //while循环的迭代器
    while (iter.hasNext){
      println(iter.next())
    }
    for (i <- list.iterator){ //for循环的迭代器
      println(i)
    }
    


      //(5) 生成字符串
    println(list.mkString(",")) //用字符串连接在一起mkString方法
      //(6) 是否包含
    println(list.contains(6)) //判断这个元素是否存在,contains方法。如果存在返回true,不存在返回false
  }
}

二、衍生集合

1、衍生集合常用方法操作

说明
(1) 获取集合的头
(2) 获取集合的尾 (不是头的都是尾)
(3) 集合最后一个数据
(4) 集合初始数据 (不包含最后一个)
(5) 反转集合
(6) 取前(后) n 个元素
(7) 去掉前(后) n 个元素
(8) 交集
(9) 并集
(10) 差集
(11) 拉链
(12) 滑窗

2、案例示例

总结:大概分两种,一个集合的操作,和两个集合的操作
一个集合
获取集合的头使用head方法,也就是集合的第一个元素。获取集合的尾,使用tail方法,注意除了头其他的元素都是尾。获取集合的最后一个元素,使用last方法。获取集合的初始数据,使用init方法,注意除了集合的最后一个元素,其他的元素都是初始数据。反转集合,使用reverse方法,这个方法很常用。取集合的前几个元素或者后几个元素,使用take()方法,里面的参数是取几个,取后几个元素用takeRight方法,相当于从后面开始取,但是输出来的元素的顺序还是没变的。去掉前几个元素或者后面几个元素,使用drop()方法,里面的参数是去掉几个元素,去掉后面几个元素使用dropRight()方法。
两个集合的操作
求两个集合的并集,使用union()方法,里面的参数是要求并集的集合,注意如果是Set集合做并集的操作的话,那么会自动去重。两个集合的交集使用intersect()方法。求两个集合的差集使用diff()方法,里面的参数第二个集合,差集的意思是就是前面那个集合有的,第二个集合没有的元素,称之为差集。求两个集合的拉链,使用zip方法,两个集合的拉链的意思是两个集合中的元素一一对应,然后返回一个二元组的形式。求集合的滑窗,这个是一个集合的操作,使用sliding()方法,里面的参数是要每一个滑窗的元素个数,滑窗的意思是第一次输出123个元素,第二次输出的是234,这样依次滑下称之为滑窗,要是里面有两个参数的话,那么第二个参数就是步长

package Scala03_shujujiegou
//衍生集合方法
class test12_yansheng {

}
object test12_yansheng{
  def main(args: Array[String]): Unit = {
    val list = List(6,12,33,45,56)
    val list2 = List(32,65,45,46,321)
  //    (1) 获取集合的头
    println(list.head) //获取集合的头使用head方法,可迭代的类型都可以用,一般在有序的类型里面有,无序的不考虑头和尾
  //    (2) 获取集合的尾 (不是头的都是尾)
    println(list.tail) //获取集合的尾用tail方法,注意除了头其他所有的元素都是尾
  //    (3) 集合最后一个数据
    println(list.last) //获取集合的最后一个元素使用last方法
  //    (4) 集合初始数据 (不包含最后一个)
    println(list.init) //init方法,除了最后一个元素,其他的元素都是初始数据
  //    (5) 反转集合
    println(list.reverse) //reverse方法,将集合给翻转过来
  //    (6) 取前(后) n 个元素
    println(list.take(3)) //取前几个元素用take方法
    println(list.takeRight(3)) //取后几个元素,用takeRight方法,从右边开始取,顺序是不变的
  //    (7) 去掉前(后) n 个元素
    println(list.drop(3)) //去掉前几个元素用drop方法
    println(list.dropRight(3)) //全掉后几个元素用dropRight方法

    //前面的都是一个集合做的操作,后面的时候基于两个集合做的操作

  //    (8) 并集
    println("==============")
    val union = list.union(list2) //求两个集合的并集也就是合在一起,使用union方法
    println("并集:"+union)
    println(list ::: list2) //获取使用 :::

    //如果是set做并集。那么重复的数据会被去重
    val set = Set(6,12,33,45,56)
    val set2 = Set(32,65,45,46,321,6)
    val union2 = set.union(set2)
    println(union2)
    println(set ++ set2)

    println("===============")
    //    (9) 交集
    val jiaoji = list.intersect(list2) //求两个集合的交集使用intersect方法
    println(jiaoji)

  //    (10) 差集
    val diff = list.diff(list2) //就是以前面那个表为基准,list里有的元素,list2里没有的元素就是差值
    println(diff)
    println("==============")
  //    (11) 拉链
    //这个拉链的意思是两个集合里的元素一一对应,返回一个一个的二元组
    println(list.zip(list2)) //两个集合的拉链使用zip方法,如果某一个集合多出来一个元素,那么就不显示那一个
  //    (12) 滑窗
    //滑窗的意思是,第一次取123元素,第二次去234,每次取三个这样滑下去,每次取多少可以定义
    println(list.sliding(3)) //滑窗使用sliding方法,里面的参数是每次滑的元素是几个,可以看到是一个迭代器
    for(i <- list.sliding(3)){ //使用类似于迭代器的方式遍历出来
      println(i)
    }
println("================")
    //要是里面有两个参数的话,第二个参数是步长,一个参数的时候默认步长是1
    for(i <- list.sliding(3,2)){
      println(i)
    }
  }
}

三、集合简单计算函数

1、常用计算操作

说明
(1) 求和
(2) 求乘积
(3) 最大值
(4) 最小值
(5) 排序

2、案例示例

总结
求集合的和使用sum方法,或者自己用增强for循环写,在外面定义一个变量初始值为0,然后进行累加。求集合里元素的乘积使用product方法。求集合里元素的最大值使用max方法。求集合里元素的最小值使用min方法。排序使用sorted方法,默认是升序,要是想降序的话,可以先排序,然后翻转列表,可以到达效果,
例如
println(list.sorted.reverse)
要是像是二元组什么的,默认是按照第一个参数排序,第一个参数是String类型的,第二个参数是Int类型的,要是想按照数字排序的话,那么就是用sortBy方法
例如println(list.sortBy(_._2))
还有第三种方法,sortWith这个方法相当于Java里面的比较器
例如println(list.sortWith((a,b) => {a<b}))如果a<b那么就不交换就是升序,可以简化为println(list.sortWith(_ < _))

package Scala03_shujujiegou
//集合常用简单计算函数
class test13_jiandanjisuan {

}
object test13_jiandanjisuan{
  def main(args: Array[String]): Unit = {
    val list:List[Int] = List(5,1,8,2,3,4)
    val list2 = List(("a",2),("c",1),("f,3"),("b",8))
  //    (1) 求和
    //自己用for循环写
    var sum = 0
    for (i <- list){
      sum += i //sum初始值为0,依次取出list列表里的值相加,最后结果不就是总和嘛
    }
    println("list的和为:"+sum)

    println(list.sum) //直接调用sum方法,直接就出来了
  //      (2) 求乘积
    println(list.product) //求成绩使用product方法
  //      (3) 最大值
    println(list.max) //求最大值使用max方法
  //      (4) 最小值
    println(list.min) //求最小值使用min方法
  //      (5) 排序
    //要做排序的话肯定是基于有序的集合类型才是有效的
    //1,sorted
    println(list.sorted) //这是升序,从小到大
    println(list.sorted.reverse) //哈哈降序可以先排序然后翻转列表,可以达到效果
    //传入隐式参数,降序排列 不传参数默认就是升序
    //println(list.sorted(Ordered[Int]))
    //2,sortBy
    //像那种二元组第一个值是String类的第二个类型是Int类型的,直接println(sortBy(_._2))就可以了,
    //3,sortWith 这个方法相当于java里的比较器
    println("================")
    println(list.sortWith((a,b) => {a<b}))  //a小于b的时候不用交换,如果a大于b就交换
    println(list.sortWith(_ < _ )) //可以直接简化成这个样子


  }
}

四、集合计算高级函数

1、语义说明

(1) 过滤
遍历一个集合并从中获取满足指定条件的元素组成一个新的集合
(2) 转换/映射(map)
将集合中的每一个元素映射到某一个函数
(3) 扁平化 (flatten)
有点像两个列表要合并,列表里面还套着列表,我们要将他打散,这样的操作就叫做扁平化
(4) 扁平化+映射 注:flatMap相当于先进行map操作,再进行flatten操作集合中的每个元素的子元素映射到某个函数并返回新的集合
(5) 分组(group)
按照指定的规则对集合的元素进行分组,分组是转换成了map
(6) 简化(reduce归约)
这个有点像reduce
(7) 折叠(fold)

2、案例示例

总结
1、过滤使用filter()函数,里面的参数是一个函数,比如选取列表中的偶数可以写为:
val list2 = list1.filter(a => a % 2 == 0) 就可以将数组中所有的偶数筛选出来
在这里插入图片描述
2、映射使用map()函数,比如将集合中的每个数*2,可以写为:
println(list1.map(a => a * 2))
在这里插入图片描述
3、扁平化使用flatten函数,两个列表合并,列表中又嵌套了列表,将列表中的元素一个个拆开,然后合并成一个新的列表,比如:println(list1.flatten)
在这里插入图片描述
4、扁平映射,使用flatMap函数,就是先映射然后进行扁平化,就是将一组单词进行分词,然后保存成新的列表,比如:
println(list1.flatMap(a => a.spilt(" "))) //split函数使用空格分割单词,然后直接完成了映射扁平操作
在这里插入图片描述
5、分组使用groupBy()函数,里面的参数也是一个函数,比如列表里面有奇数和偶数:
println(list.groupBy(_ % 2)) 对2取余就只有两个结果一个是0,一个是1,然后就会自动分成两个组
再比如有一个需求,列表里都是单词,然后按照单词的首字母进行分组,首字母一样的都是一个组:
println(list.groupBy(a => a.charAT(0))) //charAt取单词的某个字母,参数是索引,然后就完成了单词的首字母的分组
在这里插入图片描述

package Scala03_shujujiegou
//集合高级计算函数
class test14_gaojijisuan {

}
object test14_gaojijisuan{
  def main(args: Array[String]): Unit = {
    val list = List(1,2,3,4,5,6,7,8,9)
    //1、过滤
    //选取偶数
    val evenlist = list.filter(a => a % 2 == 0) //这里面传入的是一个函数
    val evenlist1 = list.filter(_ % 2 ==0 ) //可以简化成这样
    println(evenlist) //取余为0那么都是偶数
    println(evenlist1)

    //取奇数
    println(list.filter(_ % 2 == 1)) //可以直接不用赋值也可以

    //2、map
    //把集合中每个数乘2
    println(list.map(_ * 2)) //传入的参数也是一个函数
    println(list.map(a => a * a)) //这个是求平反方,这个就不能用_ * _了因为没有两个参数

    println("================")
    //3、扁平化
    //列表合并,将每一个列表拆成一个一个的元素,这种操作就是扁平化
    val list3:List[List[Int]] = List(List(1,2,3),List(4,5,6),List(6,7,8,9)) //这里这里面是list里面嵌套一个list
    val flatlist =list3(0) ::: list3(1) ::: list3(2) //先用索引吧每一个列表取出来,然后用:::合并在一起
    println(flatlist)

    //flatten ,上面那种方式要是数据非常的多那么就非常麻烦一个一个写出来,flatten方法一下就出来了
    val flatlist2 = list3.flatten //直接用flatten方法就完成了扁平化了
    println(flatlist2)

    println("=================")
    //4、扁平映射
    //将一组字符串进行分词,并保存成单词的列表
    //split方法是java里面的,包装在scala里面就是Array[String]类型的一个数组。所以相当于用map函数进行了映射,将这个数组转化为List
    val strings: List[String] = List("hello","word","scala","hello scala","hello java","we study")
    val split:List[Array[String]] = strings.map(a => a.split(" ")) //使用split方法,空格拆分
    val flattenList = split.flatten //首先经过映射之后,再调用flatten方法进行扁平化处理
    println(flattenList)
    println(split.flatten)

    //有个更简单的操作,flatMap函数,直接包含了先映射再扁平的这两步操作
    val flatmapList = strings.flatMap(a => a.split(" "))//相当于直接进行了转换然后在传入spilt操作
    println(flatmapList)

    println("==============")
    //5、分组groupBy
    //直接列表有奇数和偶数,直接分成两组
    val groupMap = list.groupBy(_ % 2) //对2取余就只有两个结果嘛一个是0,一个是1,然后这两种结果分为两个组了
    val groupMap2 = list.groupBy(a => { //用上面那个就行了
      if(a % 2 ==0){
        println("偶数")
      }else{
        println("奇数")
      }
    })
    println(groupMap)
    println(groupMap2)

    //给定一组词汇,按照单词的首字母进行分组
    val wordList = List("china","aex","alice","canda","cary","bob","japan")
    println(wordList.groupBy(a => a.charAt(0))) //charAt方法取单词的首字母


  }
}

(6) 简化(reduce归约)
sum都是一个归约操作,里面参数是两个相同类型的,最后最后结果就是一个数字
例如:println(list.reduce((a,b) => a * b))
(7) 折叠(fold)
折叠操作和reduce是一样的,有一个初始值,
例如:println(list.fold(10)(_ + _)) //然后初始值在前面 10 + 然后后面列表里的数依次相加
注意:reduce和fold折叠的区别就在于,fold有初始值,reduce没有初始值
在这里插入图片描述

package Scala03_shujujiegou
//高级计算函数
class test14_gajijisuan2 {

}
object test14_gajijisuan2{
  def main(args: Array[String]): Unit = {
    //reduce 类
    val list = List(1,2,3,4,5,6,7,8,9)

    //1、reduce (规约)
    println(list.reduce((a,b) => a * b))//里面的参数是一个函数,其实sum就是一个规约操作,最后只剩下了一个数

    val list2 = List(3,4,5,8,10)
    println(list2.reduce(_ - _)) //默认是reduceLeft,跟reduceRight不一样
    println(list2.reduceRight(_ - _)) //他这个结果是一个尾递归底层是这样的3-(4-(5-(8-10))) 结果就是-6

    println("=======================")
    //2、fold(折叠)
    // 过程:10 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
    println(list.fold(10)(_ + _)) //前面那个参数是初始值,后面那个参数是操作。比如数组加起来45然后加个10
    println(list.foldLeft(10)(_ - _)) //10 - 1 -2 -3 -4 -5 -6 -7 -8 -9
    println(list.foldRight(10)(_ - _)) // 1 -(2 -(3 -(4 -(5 -(6 -(7 -(8 -(9 -10))))))))) 先是 9 -10
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/150136.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Release库与Debug库混用导致释放堆内存时产生异常的详细分析

目录 1、问题描述 2、使用Windbg启动Debug版本的exe程序进行分析 3、进一步分析 4、问题复盘 5、为什么Debug库与Release库混用可能会出异常&#xff1f; 6、最后 VC常用功能开发汇总&#xff08;专栏文章列表&#xff0c;欢迎订阅&#xff0c;持续更新...&#xff09;ht…

DM8:dexpdimp-逻辑导出--逻辑导入

DM8:dexp&dimp-逻辑导出--逻辑导入1 dexp逻辑导出dmp文件1.1 全库导出命令附加的参数信息1.2 导出用户所拥有权限的数据库对象-命令附加的参数信息1.3 导出用户所拥有权限的数据库对象-命令附加的参数信息2 dimp--逻辑导入dmp文件2.1 全库导入dmp数据文件-命令附加的参数信…

人体姿态估计-论文精读--DeepPose: Human Pose Estimation via Deep Neural Networks

图 1. 除了关节的极端变异性外&#xff0c;许多关节几乎不可见。我们能猜测左图中右臂的位置&#xff0c;因为我们看到了姿势的其余部分&#xff0c;并预测了这个人的运动或活动。同样&#xff0c;右边的人的左半身也根本看不见。这些都是需要进行整体推理的例子。我们相信DNNs…

php处理支付宝应用网关给接口发送的post参数

php如何接收支付宝应用网关发送的POST请求方式,参数又是GET请求的数据格式配置支付宝应用网关如何接收支付宝异步通知(应用网关接收请求)将&连接的参数分割成数组实例&#xff1a;难点配置支付宝应用网关 首先要在服务器上写一个接口,然后将接口的访问地址设置在支付宝应用…

手把手教Arthas,不再怕排查线上问题了

Arthas是alibaba开源的java诊断工具&#xff0c;支持jdk6&#xff0c;采用命令行交互模式&#xff0c;可以防败的定位和诊断线上的程序运行问题。官方文档&#xff1a;https://arthas.aliyun.com/doc/一、Arthas使用场景是否有一个全局视角来查看系统的运行状况&#xff1f;为什…

六种方式,教你在SpringBoot初始化时搞点事情!

前言 在实际工作中总是需要在项目启动时做一些初始化的操作&#xff0c;比如初始化线程池、提前加载好加密证书....... 那么经典问题来了&#xff0c;这也是面试官经常会问到的一个问题&#xff1a;有哪些手段在Spring Boot 项目启动的时候做一些事情&#xff1f; 方法有很多…

卷积层里的多输入多输出通道、池化层

多输入多通道每个通道都有一个卷积核&#xff0c;结果是所有通道卷积结果的和。无论有多少输入通道&#xff0c;到目前为止我们只用到单输出通道。可以有多个三维卷积核&#xff0c;每个核生成一个输出通道。输出通道数是卷积层的超参数。每个输入通道有独立的二维卷积核&#…

为什么JavaScript这么难学啊?

前言 觉得Js难其实是很正常的&#xff0c;首先这证明你在某些知识点上没有理解透彻&#xff0c;JS挺多的知识点点其实是比较抽象的&#xff0c;比如闭包、原型和原型链等&#xff0c;其次便是不会变通运用&#xff0c;这主要是敲代码熟练度的问题&#xff0c;所以我针对你这种…

架构运维篇(六):MySQL 8.0启用BinLog 支持

上一篇&#xff1a;架构运维篇&#xff08;五&#xff09;&#xff1a;Centos7/Linux中安装RocketMQ 最新线上的项目终于到多个数据执行的问题&#xff0c;找了团队DBA发现云上的MySQL 默认是没有启用BinLog支持。 小编研究了一下很简单&#xff0c;不过中间也遇到一些坑可以给…

结构重参数化(Structural Re-Parameters)PipLine

文章目录BASICSstrcutural Inception算法思想算法核心算法架构Re-Parameter四部曲&#xff1a;ACNetACNet原理ACNet分析涨点原因推理阶段融合机制Re-Parameter四部曲&#xff1a;RepVGGRepVGG原理RepVGG分析RepVGG BlockStructural Re-Parameters融合conv2d和BN融合1x1conv转换…

【一文讲通】样本不均衡问题解决--下

1欠采样、过采样欠采样&#xff1a;减少多数类的数量&#xff08;如随机欠采样、NearMiss、ENN&#xff09;。过采样&#xff1a;尽量多地增加少数类的的样本数量&#xff08;如随机过采样、以及2.1.2数据增强方法&#xff09;&#xff0c;以达到类别间数目均衡。还可结合两者做…

地址解析协议ARP

目录地址解析协议ARP1、流程2、动态与静态的区别3、ARP协议适用范围地址解析协议ARP 如何从IP地址找出其对应的MAC地址&#xff1f; 1、流程 ARP高速缓存表 当主机B要给主机C发送数据包时&#xff0c;会首先在自己的ARP高速缓存表中查找主机C的IP地址所对应的MAC地址&#xf…

Linux常用命令——lsblk命令

在线Linux命令查询工具 lsblk 列出块设备信息 补充说明 lsblk命令用于列出所有可用块设备的信息&#xff0c;而且还能显示他们之间的依赖关系&#xff0c;但是它不会列出RAM盘的信息。块设备有硬盘&#xff0c;闪存盘&#xff0c;cd-ROM等等。lsblk命令包含在util-linux-ng…

ES报文辅助生成工具-JavaFX

此程序为基于 Java8 开发的 JavaFX Maven 工程&#xff0c;是 Java 组装ElasticSearch请求报文工具的辅助 Java 代码生成工具&#xff0c;方便开发者快速编写代码。现学现用&#xff0c;写得不好。 工具界面 代码 pom.xml <project xmlns"http://maven.apache.org/P…

Android:URLEncoder空格被转码为“+”号

Android前段和后端接口交互时&#xff0c;经常会遇到特殊字符&#xff0c;比如表情、特殊标点等&#xff0c;这样在Url中是无法识别的&#xff0c;需要进行转码&#xff0c;后端进行解码交互。 但当使用URLEncoder时&#xff0c;会发现字符串中的空格被转换成“”号&#xff0…

客服系统即时通讯IM开发(四)网站实现实时在线访客列表【唯一客服】网站在线客服系统...

在使用我的客服系统时&#xff0c;如果引入了我的js &#xff0c;就可以实时看到网站上的所有访客了 使用 WebSocket 技术来实现实时通信。 在访客登录或退出时&#xff0c;向指定客服的 WebSocket 客户端发送消息。例如&#xff0c;你可以在访客登录时&#xff0c;向指定客服…

测试用例的设计? 万能公式

万能公式(必背)&#xff1a;功能测试性能测试界面测试兼容性测试易用性测试安全测试功能测试 &#xff1a;可能来自于需求文档&#xff0c;也可能来自生活经验性能测试 &#xff1a;功能没有问题不代表性能是ok的&#xff0c;性能往往体现在一些极端情况界面测试 &#xff1a;颜…

Prometheus-基于Consul的自动注册

一、背景介绍 如果我们的物理机有很多&#xff0c;不管是基于"file_sd_config"还是"kubernetes_sd_config"&#xff0c;我们都需要手动写入目标target及创建目标service&#xff0c;这样才能被prometheus自动发现&#xff0c;为了避免重复性工作过多&#…

【182】Java8利用二叉查找树实现Map

本文利用二叉查找树写了一个Map&#xff0c;用来保存键值对。 二叉查找树的定义 二叉查找树又名二叉搜索树&#xff0c;英文名称是 Binary Search Tree&#xff0c;缩写BST。 二叉排序树&#xff0c;英文名称是 Binary Sorted Tree&#xff0c;缩写BST。 二叉查找树、二叉搜…

excel实用技巧:如何构建多级下拉菜单

使用数据有效性制作下拉菜单对大多数小伙伴来说都不陌生&#xff0c;但说到二级和三级下拉菜单大家可能就不是那么熟悉了。什么是二级和三级下拉菜单呢&#xff1f;举个例子&#xff0c;在一个单元格选择某个省后&#xff0c;第二个单元格选项只能出现该省份所属的市&#xff0…