侧边栏壁纸
博主头像
Z同学博主等级

工作磨平激情前,坚持技术的热忱。 欢迎光临Z同学的技术小站。 分享最新的互联网知识。

  • 累计撰写 290 篇文章
  • 累计创建 57 个标签
  • 累计收到 98 条评论

Kotlin 集合 转换,过滤和检测

Z同学
2021-09-30 / 0 评论 / 0 点赞 / 955 阅读 / 7,062 字
温馨提示:
本文最后更新于 2021-11-18,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

前言

在介绍了集合的基本操作后Kotlin 集合 基本介绍 - Z同学 (zinyan.com),本篇文章主要介绍集合的进阶操作:

映射转换,合拢转换,关联转换,集合的几种参数数据过滤。

转换

所谓的转换,就是在保持原有集合数据不变的情况下,基于原集合数据和自定义的判断逻辑创建一个新的集合。

简化:用老集合的数据,创建一个新的集合。两个集合互相独立。

List和Set的映射转换

通过Kotlin提供的map()的一系列方法我们可以针对集合做一个新的映射生成。

示例1:

fun main(string: Array<String>) {
    //创建一个 set 集合对象  是int类型的 并且可以编辑的数组
  val mem = mutableSetOf(1,2,3)
    println(mem) //可以得到 [1,2,3] 的输出结果
    //进行映射操作
    val maps = mem.map { it *3 } //将所有参数进行*3 操作
    //针对mem 进行修改后,maps会修改么?
    mem.remove(3)
    println(maps) //可以得到 [3,6,9] 的输出结果
    println(mem)
}
//输出
[1, 2, 3]
[3,6, 9]
[1, 2]

可以看到,我们针对老数据进行修改后,新集合数据没有变动。

针对新集合操作后,老数据也不会产生变动。两个集合是独立的。

如果,我们在映射的时候,不只是想利用参数,还想利用下标呢?有方法:mapIndexed

示例2:

fun main(string: Array<String>) {
    //创建一个 set 集合对象  是int类型的
    val mem = mutableSetOf(1, 2, 3)
    println(mem) //可以得到 [1,2,3] 的输出结果
    //进行映射操作
    val maps = mem.mapIndexed { index, i ->
        //index 就是下标值
        // i 就是参数值  参数值,就是两个数据的返回值
       i + index
    }
    println(maps)
}
//输出
[1, 2, 3]
[1, 3, 5]

我们也可以根据结果,映射成其他类型的集合

示例3:

fun main(string: Array<String>) {
    //创建一个 set 集合对象  是int类型的
    val mem = mutableSetOf(1, 2, 3)
    println(mem) //可以得到 [1,2,3] 的输出结果
    //进行映射操作
    val maps = mem.mapIndexed { index, i ->
        if(index==2){
            "这是个2"
        }else{
            "Index:$i"
        }
    }
    println(maps)
}
//输出
[1, 2, 3]
[Index:1, Index:2, 这是个2]

类似的方法还有:

mapNotNull(), mapIndexedNotNull() 等可以通过传null。来过滤掉定义的值

示例:

fun main(string: Array<String>) {
    //创建一个 set 集合对象  是int类型的
    val mem = mutableSetOf(1, 2, 3)
    println(mem) //可以得到 [1,2,3] 的输出结果
    //进行映射操作
    val maps = mem.mapNotNull {
        if (it == 1) { //过滤掉参数值为1的数据
            null
        } else
            it
    }
    println(maps)
}
//输出
[1, 2, 3]
[2, 3]

Map的映射转换

相对于List和Set 对象。Map有key和value 我们能够通过mapKeysmapValues针对map的特性进行转换

示例1:我们映射了一个新的map对象,将全部的key都进行了替换。

fun main(string: Array<String>) {
    //创建一个 map 集合对象  是int类型的
    val mem = mapOf("key1" to 10,"key2" to 20,"key3" to 3)
    println(mem)
    val mpas = mem.mapKeys {
        "Zinyan-${it.key}"
    }
    println(mpas)
}
//输出
{key1=10, key2=20, key3=3}
{Zinyan-key1=10, Zinyan-key2=20, Zinyan-key3=3}

示例2:映射一个新的map对象,将全部的value进行替换

fun main(string: Array<String>) {
    val mem = mapOf("key1" to 10,"key2" to 20,"key3" to 3)
    println(mem)
    val mpas = mem.mapValues {
        it.value+1
    }
    println(mpas)
}
//输出
{key1=10, key2=20, key3=3}
{key1=11, key2=21, key3=4}

同时,也有null方法

类似的方法还有:

mapNotNull(), 可以通过传null。来过滤掉指定的值。

合拢转换 Zip

关键字就是zip函数。能够将两个集合数组合并成一个二维数组的情况。

合并后的数据是一个Pair对象的List集合,合并后的对象是一个List<Pair>对象。

示例1:

fun main(string: Array<String>) {
    val n1 = listOf("a", "b", "c", "d")
    val n2 = listOf("ZZ", "XX", "YY")
    val ss = n1 zip n2 //n1和n2的合并
    println(ss)
    val zz = ss zip n1 // 合并结果再次和n1 合并
    println(zz)
    val sz = n1 zip n1  //集合和自己合并
    println(sz)
}
//输出
[(a, ZZ), (b, XX), (c, YY)]
[((a, ZZ), a), ((b, XX), b), ((c, YY), c)]
[(a, a), (b, b), (c, c), (d, d)]

通过数据我们可以知道。两个集合的长度,在合并后结果是按照下标共有区域进行的合并。

也就是哪个集合长度最小,那么就按照最小长度进行合并。

如果我们希望zip 合并后的数据是一个普通集合该怎么做?

示例2:

fun main(string: Array<String>) {
    val n1 = listOf("a", "b", "c", "d")
    val n2 = listOf("ZZ", "XX", "YY")
    val ss = n1.zip(n2) { n1, n2 ->
        "结果:$n1:$n2"
    } //n1和n2的合并
    println(ss)
}
//输出
[结果:a:ZZ, 结果:b:XX, 结果:c:YY]

这个例子输出的就是一个List<String>。 我们也可以基于该方式,合并后其他数据格式。

针对已经合并的集合,我们可以调用unzip()方法,分解

示例3:

fun main(string: Array<String>) {
    val n1 = listOf("a", "b", "c", "d")
    val n2 = listOf("ZZ", "XX", "YY")
    val ss = n1 zip n2
    println(ss)
    val sss = ss.unzip()
    println(sss)
    println("First:${sss.first}")
    println("Second:${sss.second}")
}
//输出
[(a, ZZ), (b, XX), (c, YY)]
([a, b, c], [ZZ, XX, YY])
First:[a, b, c]
Second:[ZZ, XX, YY]

关联转换 associate

关联转换允许从集合元素和与其关联的某些值构建map。相对于其他的转换,关联转换会根据逻辑转换成Map对象。

示例1:

fun main(string: Array<String>) {
    val n1 = listOf("aa", "bb", "c", "dddd")
    //关联集合,计算value的值
    val ass = n1.associateWith {
        it.length
    }
    println(ass)
    println("keys:${ass.keys}")
    println("values:${ass.values}")
    
    val ss = n1.associate {
        Pair(it, it)
    }
    println(ss)
}
//输出
{aa=2, bb=2, c=1, dddd=4}
keys:[aa, bb, c, dddd]
values:[2, 2, 1, 4]
{aa=aa, bb=bb, c=c, dddd=dddd}

还有其他的几种函数。功能都是转换

associateByassociateTo等等

将集合对象的值作为关联转换后的值。

示例:

fun main(string: Array<String>) {
    val n1 = listOf("aa", "bb", "c", "dddd")
    //关联集合,计算计算key
    val ss = n1.associateBy {
        it.first()
    }
    println(ss)
}
//输出
{a=aa, b=bb, c=c, d=dddd}

二维数组的一维输出 flatten

我们可以通过flattenflatMap 函数。进行拆解多维嵌套集合

示例1:

val n1 = listOf(setOf(1,2,3), setOf("a","b","c"), setOf(9,8,7,6))
println(n1)
val ss = n1.flatten()
println(ss)

//输出
[[1, 2, 3], [a, b, c], [9, 8, 7, 6]]
[1, 2, 3, a, b, c, 9, 8, 7, 6]

示例2:

fun main(string: Array<String>) {

    val s1 = listOf(listOf(1, "b", 4), listOf("a", "b", "c"))
    println(s1)
    val sss =s1.flatMap {
       it.asIterable()
    }
    println(sss)
}
//输出
[[1, b, 4], [a, b, c]]
[1, b, 4, a, b, c]

flatMap对象遍历每个元素后,它需要的返回值是Iterable对象才行

过滤 filter

针对集合的常用需求。Kotlin通过使用lambda表达式来实现匹配判断。

该表达式返回true:说明给定元素匹配,false:表明给定元素不匹配。

过滤操作并不会针对原始数据做处理

过滤关键函数是filter()

示例1:

fun main(string: Array<String>) {
   
    val word = mutableListOf("A", "B", "C", "E", "D", "F")
    val ss = word.filter { it.equals("F") }
    println(word)
    println(ss)
}
//输出
[A, B, C, E, D, F]
[F]

其中filter只能检测元素的值,进行过滤。如果我们需要元素下标值参与。那么就可以使用filterIndexed{},

但是我们如果有需求,得到集合中取反向呢?那么我们可以使用filterNot

示例2: 我们需要获取集合中不是F的字符 filterNot

fun main(string: Array<String>) {
   
    val word = mutableListOf("A", "B", "C", "E", "D", "F")
    val ss = word.filterNot { it ->
        it.equals("F") 
    }
    println(word)
    println(ss)
}
//输出
[A, B, C, E, D, F]
[A, B, C, E, D]

filterIsInstance 返回给定类型的元素

主要是处理泛型List 的筛选

示例1:

fun main(string: Array<String>) {
 
    val word = listOf(null, 1, "A", 1.0f, "zzzz")
    println(word)
    //获取数组中的字符串
    val ss = word.filterIsInstance<String>()
    println(ss)

    val num = word.filterIsInstance<Int>()
    println(num)
}
//输出
[null, 1, A, 1.0, zzzz]
[A, zzzz]
[1]

过滤掉空值

示例

fun main(string: Array<String>) {
    val word = listOf(null, 1, "A", 1.0f, "zzzz")
    println(word)
    //获取数组中的字符串
    val ss = word.filterNot {
        it == null
    }
    println(ss)
}
//输出
[null, 1, A, 1.0, zzzz]
[1, A, 1.0, zzzz]

划分 partition 过滤

可以将集合划分为两个集合结果。将会得到过滤结果集和过滤剩下结果集。

示例:

fun main(string: Array<String>) {
    val num = listOf("A", "B", "C", "D", "E", "F")
    val (n1, n2) = num.partition { it.equals("C") || it.equals("D") }
    println(n1)
    println(n2)
}
//输出
[C, D]
[A, B, E, F]

检测 any,none,all

  • 如果至少有一个元素匹配,那么 any() 返回 true

  • 如果没有元素匹配,那么 none() 返回 true

  • 如果所有元素都匹配,那么 all() 返回 true

    注意,在一个空集合上调用 all() 都会返回 true 。这种行为在逻辑上被称为 [*vacuous truth*](https://en.wikipedia.org/wiki/Vacuous_truth)。

示例1:

fun main(string: Array<String>) {
    val num = listOf("A", "B", "C", "D", "E", "F")
    //检测list中是否有A
    println(num.any { it.equals("A") })
    //和any检测相反
    println(num.none { it.equals("A") })
    //所有项都必须是A的时候就返回ture。
    println(num.all { it.equals("A") })
}
//输出
true
false
false

如果any和none不带比较参数时。就是检测List 是否为空

示例2:

fun main(string: Array<String>) {
    val num = listOf("A", "B", "C", "D", "E", "F")
    //如果不带参数时,就会检测集合是否有元素。
    println(num.any())
    //和any检测相反
    println(num.none())

    val num1 = listOf(null)  //空元素也是有元素
    println(num1.any())

    val num2 = listOf<String>()  //空元素,所以返回false
    println(num2.any())
}
//输出
true
false
true
false
0

评论区