切片(slice)

切片是动态数组,比数组灵活。数组长度不可变,但是切片可以追加。 切片原型定义如下:

struct Slice
{
  byte *array;
  unit32 len;
  unit32 cap;
};

它抽象为以下三个部分:
1. 指向被引用的底层数组的指针;
2. 切片中元素的个数;
3. 切片分配的存储空间。

声明、定义和初始化

声明一个切片:

var sliceTest []int
  • 声明的切片是nil,不初始化无法插入数据
  • 跟map一样,通过make定义切片
make([]T, length, capacity)
  • length为初始长度,为必须参数。capacity为指定容量,可选。
    例如:
sliceTest = make([]int, 10)
  • 直接初始化切片
sliceTest1 := [] int {1,2,3}
  • 引用赋值

s := arr[startIndex:endIndex]

初始化s,是arr从startIndex到endIndex的引用

s := sliceTest1[:]//s表示sliceTest的引用
s1 := sliceTest[1]

append

  • append主要用于给某个切片(slice)追加元素
  • 如果该切片存储空间(cap)足够,就直接追加,长度(len)变长;如果空间不足,就会重新开辟内存,并将之前的元素和新的元素一同拷贝进去
  • 第一个参数为切片,后面是该切片存储元素类型的可变参数

代码例子

package main

import (
    "fmt"
)

func main(){
    var sliceTest []int
    //声明的切片是nil
    if sliceTest == nil {
        fmt.Println("slice is nil")
    }
    //用make创建切片,制定默认长度
    sliceTest = make([]int, 2)
    sliceTest[0] = 1
    fmt.Printf("len:%d, cap:%d\n", len(sliceTest), cap(sliceTest))
    sliceTest[1] = 2
    //通过range遍历切片
    for i, v := range sliceTest{
        fmt.Printf("index:%d, value:%d\n", i, v)
    }
    //切片默认长度是2,不能直接通过下标增加长度
    //sliceTest[2] = 2 //程序崩溃,提示"panic: runtime error: index out of range"
    //sliceTest[3] = 3
    //通过append添加元素到切片中
    sliceTest = append(sliceTest, 3)
    fmt.Printf("len:%d, cap:%d\n", len(sliceTest), cap(sliceTest))//第一次append将cap增加了2
    sliceTest = append(sliceTest, 4)
    fmt.Printf("len:%d, cap:%d\n", len(sliceTest), cap(sliceTest))//第二次append,因为还有空间,cap没增加
    for i := 0; i < len(sliceTest); i++ {
        fmt.Printf("index:%d, value:%d\n", i, sliceTest[i])
    }

    s := sliceTest[:]//s引用sliceTest
    fmt.Printf("s, len:%d, cap:%d\n", len(s), cap(s))
    for i := 0; i < len(s); i++ {
        fmt.Printf("s, index:%d, value:%d\n", i, s[i])
    }

    s1 := s[2:4]//s1引用s下标2-4的元素(不包含下标4)
    fmt.Printf("s1, len:%d, cap:%d\n", len(s1), cap(s1))
    for i := 0; i < len(s1); i++ {
        fmt.Printf("s1, index:%d, value:%d\n", i, s1[i])
    }
    s1[1] = 14 //改变s1中的值
    for i := 0; i < len(sliceTest); i++ {
        fmt.Printf("sliceTest, index:%d, value:%d\n", i, sliceTest[i])//因为切片是引用类型,所以修改会反应到sliceTest中
    }
    s2 := s[:2]
    fmt.Printf("s2, len:%d, cap:%d\n", len(s2), cap(s2))
    for i := 0; i < len(s2); i++ {
        fmt.Printf("s2, index:%d, value:%d\n", i, s2[i])
    }
    s2 = append(s2, 23)//s2的cap=4,len=2,空间充足,直接追加
    fmt.Printf("s2, len:%d, cap:%d\n", len(s2), cap(s2))
    for i := 0; i < len(sliceTest); i++ {//sliceTest跟s2指向同一个slice,所以
        fmt.Printf("sliceTest, index:%d, value:%d\n", i, sliceTest[i])
    }
    s2 = append(s2, 24)
    fmt.Printf("s2, len:%d, cap:%d\n", len(s2), cap(s2))
    for i := 0; i < len(sliceTest); i++ {
        fmt.Printf("sliceTest, index:%d, value:%d\n", i, sliceTest[i])
    }
    for i := 0; i < len(s2); i++ {
        fmt.Printf("s2, index:%d, value:%d\n", i, s2[i])
    }

    s3 := append(s2, 25, 26, 27)//s2继续添加,因为容量不够,所以要从新分配内存,将之前的元素copy过去,再赋值给s3。此时s2没有变,还是sliceTest的引用
    s2[0] = 21//此时更改s2[0],会更改到sliceTest[0]
    s3[0] = 31//此时更改s3[0],不会更改到sliceTest[0]
    fmt.Printf("s2, len:%d, cap:%d\n", len(s2), cap(s2))
    fmt.Printf("s3, len:%d, cap:%d\n", len(s3), cap(s3))
    for i := 0; i < len(sliceTest); i++ {
        fmt.Printf("sliceTest, index:%d, value:%d\n", i, sliceTest[i])
    }
    for i := 0; i < len(s2); i++ {
        fmt.Printf("s2, index:%d, value:%d\n", i, s2[i])
    }
    for i := 0; i < len(s3); i++ {
        fmt.Printf("s3, index:%d, value:%d\n", i, s3[i])
    }

}
Fluent Python 中的切片slice)功能是处理序列数据时非常强大且灵活的工具。通过合理使用切片,可以实现对列表、字符串、元组等序列类型的高效访问和操作。以下是对 Fluent Slice 功能的使用指南及切片操作方法的详细说明。 ### 切片的基本语法 在 Python 中,切片的基本语法为 `sequence[start:stop:step]`,其中: - `start`:起始索引,默认为 0。 - `stop`:结束索引(不包含该位置的元素),默认为序列的末尾。 - `step`:步长,默认为 1。 例如: ```python s = "abcdefgh" print(s[2:5]) # 输出 'cde' print(s[:4]) # 输出 'abcd' print(s[::2]) # 输出 'aceg' ``` ### 使用 slice() 函数 除了直接使用切片语法外,还可以通过内置的 `slice()` 函数来创建一个切片对象,然后将其应用于序列中。这种方式特别适用于需要将切片逻辑封装或传递的情况。 ```python desc_slice = slice(6, 40) s = "This is a very long string that we want to slice" print(s[desc_slice]) # 等价于 s[6:40] ``` 上述代码中的 `slice(6, 40)` 表示从第 6 个字符开始,到第 39 个字符结束(不包括第 40 个字符)[^1]。 ### 处理多维数据 虽然 Python 原生不支持多维切片,但像 NumPy 这样的第三方库提供了类似的功能,允许使用如 `a[m:n, j:k]` 的形式进行多维切片操作。这对于处理矩阵或数组非常有用。 ```python import numpy as np arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(arr[0:2, 1:3]) # 输出 [[2 3] # [5 6]] ``` ### indices 方法的应用 当处理动态生成的切片参数时,`slice.indices(len)` 方法可以帮助将负数索引转换为正数,并确保所有索引都在有效范围内。这对于编写健壮的切片处理代码非常有帮助。 ```python sl = slice(-3, None, 2) indices = sl.indices(10) # 返回 (7, 10, 2) print(list(range(*indices))) # 输出 [7, 9] ``` 此方法接受一个整数参数 `len`,表示目标序列的长度,并返回一个三元组 `(start, stop, step)`,其中所有的负数索引都被转换为相对于序列末尾的位置,超出范围的索引会被截断至合法范围[^4]。 ### 结论与最佳实践 - **理解切片规则**:熟悉 `start`, `stop`, `step` 的作用及其默认值,能够更有效地利用切片功能。 - **使用 slice() 对象**:在需要复用或传递切片逻辑时,使用 `slice()` 创建的对象可以提高代码的可读性和灵活性。 - **探索第三方库**:对于复杂的多维数据处理任务,考虑使用 NumPy 等支持多维切片的库。 - **利用 indices() 方法**:处理不确定的切片参数时,调用 `indices()` 可以避免索引越界错误,使代码更加健壮。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值