一日一技:在 Golang 中如何快速判断字符串是否在一个数组中

简介: 一日一技:在 Golang 中如何快速判断字符串是否在一个数组中

摄影:产品经理继续跟产品经理吃大餐

在使用 Python 的时候,如果要判断一个字符串是否在另一个包含字符串的列表中,可以使用in 关键词,例如:

name_list = ['pm', 'kingname', '青南']
if 'kingname' in name_list:
    print('kingname 在列表里面')

但是,Golang 是没有in这个关键词的,所以如果要判断一个字符串数组中是否包含一个特定的字符串,就需要一个一个对比:

package main
import "fmt"
func in(target string, str_array []string) bool {
     for _, element := range str_array{
        if target == element{
            return true
        }
    }
    return false
}
func main(){
    name_list := []string{"pm", "kingname", "青南"}
    target1 := "kingname"
    target2 := "产品经理"
    result := in(target1, name_list)
    fmt.Println("kingname 是否在 name_list 中:", result)
    result = in(target2, name_list)
    fmt.Println("产品经理是否在 name_list 中:", result)
}

运行效果如下图所示:

但这种方式有一个弊端,就是要遍历整个字符串数组。如果数组里面有100万条数据,那么平均要遍历50万次才能找到。这是一个非常费时间的操作。

有没有什么办法可以优化这个操作呢?

如果是有序的整型数组,那么我们可以使用二分查找,把时间复杂度O(n)降到对数时间复杂度。字符串能不能也这样操作呢?实际上是可以的。

在 Golang 中,有一个排序模块sort,它里面有一个sort.Strings()函数,可以对字符串数组进行排序。同时,还有一个sort.SearchStrings()[1]函数,会用二分法在一个有序字符串数组中寻找特定字符串的索引。

结合两个函数,我们可以实现一个更高效的算法:

package main
import (
        "fmt"
        "sort"
    )
func in(target string, str_array []string) bool {
    sort.Strings(str_array)
    index := sort.SearchStrings(str_array, target)
    if index < len(str_array) && str_array[index] == target {
        return true
    }
    return false
}
func main(){
    name_list := []string{"pm", "kingname", "青南"}
    target1 := "kingname"
    target2 := "产品经理"
    result := in(target1, name_list)
    fmt.Println("kingname 是否在 name_list 中:", result)
    result = in(target2, name_list)
    fmt.Println("产品经理是否在 name_list 中:", result)
}

运行效果如下图所示:

其中,sort.Strings是一个 in-place 的修改方式,是直接修改的 str_array。修改以后str_array变成有序的字符串数组。接下来通过二分查找快速定位。如果找到了,那么返回目标字符串在排序后的列表中第一次出现的索引。如果没有找到,那么返回数组中最后一个元素的索引。所以只要 index 小于最后一个元素的索引,那么目标字符串肯定存在;如果等于最后一个元素的索引,但是值不等于最后一个元素,那么目标字符串就不存在于字符串数组中。

通过先排序再查询的方式,对于100万个元素的字符串数组,只需要查询20次左右就能确认字符串是否存在。速度大大提升。

最后考大家一个思考题。name_list一开始是乱序的字符串数组,在上图第23行,如果打印一下 name_list,打印出来的是经过排序的,还是没有经过排序的字符串数字?

目录
相关文章
|
1天前
|
存储 Go 开发者
Golang深入浅出之-Go语言字符串操作:常见函数与面试示例
【4月更文挑战第20天】Go语言字符串是不可变的字节序列,采用UTF-8编码。本文介绍了字符串基础,如拼接(`+`或`fmt.Sprintf()`)、长度与索引、切片、查找与替换(`strings`包)以及转换与修剪。常见问题包括字符串不可变性、UTF-8编码处理、切片与容量以及查找与替换的边界条件。通过理解和实践这些函数及注意事项,能提升Go语言编程能力。
28 0
|
1天前
|
Go
【Golang】使用泛型对数组进行去重
【2月更文挑战第11天】使用泛型对数组进行去重
31 0
|
1天前
|
Go
Golang拼接字符串性能对比
【2月更文挑战第8天】Golang拼接字符串性能对比
45 2
|
1天前
|
Java 容器 程序员
Java语言程序设计试卷6套
Java语言程序设计试卷6套
170 0
Java语言程序设计试卷6套
|
1天前
|
Java Go C++
Golang每日一练(leetDay0120) 反转字符串中的元音字母、前K个高频元素
Golang每日一练(leetDay0120) 反转字符串中的元音字母、前K个高频元素
35 0
Golang每日一练(leetDay0120) 反转字符串中的元音字母、前K个高频元素
|
1天前
|
Go 机器学习/深度学习 Rust
Golang每日一练(leetDay0119) 反转字符串I\II Reverse String
Golang每日一练(leetDay0119) 反转字符串I\II Reverse String
40 0
Golang每日一练(leetDay0119) 反转字符串I\II Reverse String
|
1天前
|
Java Go C++
Golang每日一练(leetDay0114) 矩阵中的最长递增路径、按要求补齐数组
Golang每日一练(leetDay0114) 矩阵中的最长递增路径、按要求补齐数组
36 0
Golang每日一练(leetDay0114) 矩阵中的最长递增路径、按要求补齐数组
|
1天前
|
Java Go C++
Golang每日一练(leetDay0088) 数组的乘积、搜索二维矩阵II
Golang每日一练(leetDay0088) 数组的乘积、搜索二维矩阵II
29 0
Golang每日一练(leetDay0088) 数组的乘积、搜索二维矩阵II
|
1天前
|
Java Go C++
Golang每日一练(leetDay0081) 基本计算器I\II Basic Calculator
Golang每日一练(leetDay0081) 基本计算器I\II Basic Calculator
30 0
Golang每日一练(leetDay0081) 基本计算器I\II Basic Calculator
|
1天前
|
算法 C++ Python
Golang每日一练(leetDay0052) 寻找旋转排序数组中的最小值I\II
Golang每日一练(leetDay0052) 寻找旋转排序数组中的最小值I\II
36 0
Golang每日一练(leetDay0052) 寻找旋转排序数组中的最小值I\II