详解Go语言如何实现字符串切片反转函数

目录
  • Python 中的 reverse 函数
  • 实现一个 reverse 反转函数
    • 利用两个切片实现
  • 前后两两原地交换
  • 反转为原切片的副本
  • 总结

Python 中的 reverse 函数

Go 语言不像其他语言如 Python,有着内置的 reverse() 函数,先来看一下 Python 中对于列表的反转方法,然后我们再来学习如果在 Go 语言中实现相同的功能。

>>> myList = [2022, 2021, 2008, 2012]
>>> myList.reverse()
>>> print("Reversed List:", myList)
Reversed List: [2012, 2008, 2021, 2022]
>>> 

实现一个 reverse 反转函数

reverse 算法取一个数据集,并将该数据集的值进行反转,Go 标准的 sort 包并没有内置的方法来反转一个切片。

利用两个切片实现

设计思想:

  • 确定切片长度
  • 获取最后一个元素
  • 以相反的顺序在新切片中添加最后一个元素到第一个位置
package main

import "fmt"

func main() {
    s := []string{"hello", "foo", "bar", "go", "abc", "zzz"}

    // 定义新的反转切片
    reverseOfS := []string{}

    // 遍历原切片 s
    for i := range s {
        reverseOfS = append(reverseOfS, s[len(s)-1-i])
    }
    fmt.Println(reverseOfS)
}

运行结果:

[zzz abc go bar foo hello]

显然,这种方式会额外花费一个相同空间的切片,空间复杂度为 O(n)

前后两两原地交换

我们可以写一个简易的 reverse 函数来进行数据的反转,通过循环原切片的一半,然后依次与对应的元素进行交换,比如::

func reverse(s []string) []string {
    for i := 0; i < len(s)/2; i++ {
        j := len(s) - i - 1
        s[i], s[j] = s[j], s[i]
    }
    return  s
}

这个函数可以通过更简短的实现,通过 Go 内部的操作进行循环:

package main

import "fmt"

func reverse(s []string) []string {
    for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
        s[i], s[j] = s[j], s[i]
    }
    return s
}

func main() {
    s := []string{"hello", "foo", "bar", "go", "abc", "zzz"}

    reverseOfS := reverse(s)

    fmt.Println(reverseOfS)
}

执行结果:

[zzz abc go bar foo hello]

但是,上面的 reverse 函数都是通过切片按值传递,其实我们在修改传递中的 []string 切片,实际上,可以通过以下方式进一步简写:

package main

import "fmt"

func reverse(s []string) {
    for i := 0; i < len(s)/2; i++ {
        j := len(s) - i - 1
        s[i], s[j] = s[j], s[i]
    }
}

func main() {
    s := []string{"hello", "foo", "bar", "go", "abc", "zzz"}

    reverse(s)
    fmt.Printf("%v\n", s)
}

此时,reverse() 函数不会返回切片的另一个引用,此时的交换就是就地进行,此时更像文章开头 Python 中的 reverse() 函数。

反转为原切片的副本

如果我们要返回切片的反转的副本,reverse 函数就可以这样写:

package main

import "fmt"

func reverse(s []string) []string {

    newS := make([]string, len(s))
    for i, j := 0, len(s)-1; i <= j; i, j = i+1, j-1 {
        newS[i], newS[j] = s[j], s[i]
    }
    return newS
}

func main() {
    s := []string{"hello", "foo", "bar", "go", "abc", "zzz"}

    fmt.Printf("原字符串切片:%v\n", s)
    fmt.Printf("反转后的切片:%v\n", reverse(s))
}

运行结果:

原字符串切片:[hello foo bar go abc zzz]
反转后的切片:[zzz abc go bar foo hello]

可以看到,原切片是没有变化的。

当然,因为我们没有就地修改原切片,因此又可以回到最初的方法 append,看代码:

func reverse(s []string) []string {

    newS := make([]string, 0, len(s))

    for i := len(s)-1; i >= 0; i-- {
        newS = append(newS, s[i])
    }
    return newS
}

运行结果图如下:

总结

本文通过 Python 中的 reverse() 函数的一个示例,引发出一个思考:Go 语言中有没有类似的反转函数?

然后通过几种方式实现同样的字符串切片的反转功能,并通过借助额外空间和就地反转两种方式实现了功能相同 reverse 函数,其实类似的反转思想也可以用于字符串或者链表反转等其他数据结构。

到此这篇关于详解Go语言如何实现字符串切片反转函数的文章就介绍到这了,更多相关Go语言字符串切片反转函数内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • golang 字符串切片去重实例

    实现目的:实现字符串切片去重,只是两个字符完全相同时,去除一个. 实现方式:考虑两种,一种是常规的双重循环去除,另一种是利用map的key的唯一性实现. 1.通过双重循环来过滤重复元素 方法1, 思路:利用for双重循环,新建一个slice,遍历原slice中的每一个元素,每一次判断这个元素和后面元素是否相同,若相同则去除,若不同则存入新slice中,判断本元素后,再继续判断下一个元素,直到判断完毕. package main import "fmt" func main() { va

  • 详解Golang 与python中的字符串反转

    详解Golang 与python中的字符串反转 在go中,需要用rune来处理,因为涉及到中文或者一些字符ASCII编码大于255的. func main() { fmt.Println(reverse("Golang python")) } func reverse(src string) string { dst := []rune(src) len := len(dst) var result []rune result = make([]rune, 0) for i := le

  • Go语言实现字符串切片赋值的方法小结

    前言 在所有编程语言中都涉及到大量的字符串操作,可见熟悉对字符串的操作是何等重要.本文通过示例详细介绍了Go语言实现字符串切片赋值的方法,感兴趣的朋友们跟着小编一起来看看吧. 1. 在for循环的range中 func StrRangeTest() { str := []string{"str1", "str2", "str3"} for i, v := range str { fmt.Println(i, v) v = "test&q

  • 详解Go语言如何实现字符串切片反转函数

    目录 Python 中的 reverse 函数 实现一个 reverse 反转函数 利用两个切片实现 前后两两原地交换 反转为原切片的副本 总结 Python 中的 reverse 函数 Go 语言不像其他语言如 Python,有着内置的 reverse() 函数,先来看一下 Python 中对于列表的反转方法,然后我们再来学习如果在 Go 语言中实现相同的功能. >>> myList = [2022, 2021, 2008, 2012] >>> myList.reve

  • 详解C语言常用的一些转换工具函数

    1.字符串转十六进制 代码实现: 2.十六进制转字符串 代码实现: 或者 效果:十六进制:0x13 0xAA 0x02转为字符串:"13AAA2" 3.字符串转十进制 代码实现: 第一种,如果带负号 这个就是atoi函数的实现: 效果:字符串:"-123" 转为 -123 第二种,如果不带负号: 效果:字符串:"123" 转为 123 第三种:包含转为浮点数: 效果:字符串:"123.456" 先转为 123456,然后除以1

  • 详解Go语言strconv与其他基本数据类型转换函数的使用

    目录 前言 strconv string 与 int 之间的转换 Itoa:int 类型转 string 类型 Atoi:string 类型转 int 类型 FormatInt:将数字转成指定进制数并以 string 类型返回 ParseInt:给定基数(进制数)和位数,返回对应十进制的值 string 与 float 之间的转换 ParseFloat:字符串类型转浮点型类型 FormatFloat:根据格式 fmt 和精度 prec 将浮点数 f 转换为字符串 string 与 bool 之间

  • 详解C语言中的字符串拼接(堆与栈)

    首先来看一个demo: int do_sth(int type) { char *errstr; switch(type) { case 1: errstr = "Error";break case 2: errstr = "Warn";break case 3: errstr = "Info";break case 4: errstr = "Debug";break default: return 0; } if (...)

  • 详解C语言中的字符串数组

    在C语言当中,字符串数组可以使用: char a[] [10]; 或者 char *a[]; 表示 第一种表示方式固定了每个字符串的最大大小.第二种没有字符串的大小限制. #include <stdio.h> #include <string.h> //该程序的功能是 输入阿拉伯数字的月份数 输出英文月份 int main() { //一个字符串数组 它的下标代表英文月份的阿拉伯数字 char *month[] = {"January","Februa

  • 详解Go语言中数组,切片和映射的使用

    目录 1.Arrays (数组) 2.切片 2.1 make创建切片 3.映射Map Arrays (数组), Slices (切片) 和 Maps (映射) 是常见的一类数据结构 1.Arrays (数组) 数组是定长的. 长度不可改变. 初始化 package main import ( "fmt" ) func main() { var scores [10]int scores[0] = 99 fmt.Printf("scoers:%d\n", scores

  • 详解C语言内核字符串转换方法

    在内核编程中字符串有两种格式ANSI_STRING与UNICODE_STRING,这两种格式是微软推出的安全版本的字符串结构体,也是微软推荐使用的格式,通常情况下ANSI_STRING代表的类型是char *也就是ANSI多字节模式的字符串,而UNICODE_STRING则代表的是wchar*也就是UNCODE类型的字符,如下文章将介绍这两种字符格式在内核中是如何转换的. 在内核开发模式下初始化字符串也需要调用专用的初始化函数,如下分别初始化ANSI和UNCODE字符串,我们来看看代码是如何实现

  • 详解C语言内核字符串拷贝与比较

    在上一篇文章<驱动开发:内核字符串转换方法>中简单介绍了内核是如何使用字符串以及字符串之间的转换方法,本章将继续探索字符串的拷贝与比较,与应用层不同内核字符串拷贝与比较也需要使用内核专用的API函数,字符串的拷贝往往伴随有内核内存分配,我们将首先简单介绍内核如何分配堆空间,然后再以此为契机简介字符串的拷贝与比较. 首先内核中的堆栈分配可以使用ExAllocatePool()这个内核函数实现,此外还可以使用ExAllocatePoolWithTag()函数,两者的区别是,第一个函数可以直接分配内

  • 详解Go语言中切片的长度与容量的区别

    目录 切片的声明 切片的长度和容量 切片追加元素后长度和容量的变化 append 函数 切片的源代码学习 切片的结构体 切片的扩容 总结 切片的声明 切片可以看成是数组的引用(实际上切片的底层数据结构确实是数组).在 Go 中,每个数组的大小是固定的,不能随意改变大小,切片可以为数组提供动态增长和缩小的需求,但其本身并不存储任何数据. // 数组的声明 var a [5]int //只指定长度,元素初始化为默认值0 var a [5]int{1,2,3,4,5} // 切片的声明 // 方法1:

  • 详解Go语言如何使用标准库sort对切片进行排序

    目录 sort 标准库 Ints 和 IntsAreSorted Float64s 和 Float64sAreSorted Strings 和 StringsAreSorted Sort Interface 对结构体切片进行排序 小结 sort 标准库 Sort 标准库提供了对基本数据类型的切片和自定义类型的切片进行排序的函数,常用函数如下表所示: 函数 描述 Ints(x []int) 对 int 类型的切片进行升序排序 IntsAreSorted(x []int) bool 判断 int 类

随机推荐