zoukankan      html  css  js  c++  java
  • Python与Go列表切片越界的对比

    需求

    很简单的知识点,做一下小结。

    最近写代码需要做一下切片的操作,比如给定这样一个切片:

    lst1 = [1,2,3,4,5,6,7,8,9,10,11,12,13]

    将这个切片里面的元素按照每4个为一组,每一组组成单独的切片,然后再组合到外层的切片中,结果像这样:

    [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13]]

    python的写法

    # -*- coding:utf-8 -*-
    
    lst1 = [1,2,3,4,5,6,7,8,9,10,11,12,13]
    lst2 = ["w","wg","wa","jj","aa","ff","gg","hh","asd","ww","ee","gg","nn","mm"]
    
    print(len(lst1)) # 13
    print(len(lst2)) # 14
    
    ### 超限切片
    ret_lst1 = list()
    ret_lst2 = list()
    
    # 根据lst1构建新的列表
    for i in range(0,len(lst1),4):
        curr_lst = lst1[i:i+4]
        ret_lst1.append(curr_lst)
    
    # 根据lst2构建新的列表
    for i in range(0,len(lst2),4):
        curr_lst = lst2[i:i+4]
        ret_lst2.append(curr_lst)
    
    ### 注意结果最后一个列表不足的话不会报错
    print(ret_lst1) # [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13]]
    print(ret_lst2) # [['w', 'wg', 'wa', 'jj'], ['aa', 'ff', 'gg', 'hh'], ['asd', 'ww', 'ee', 'gg'], ['nn', 'mm']]

    Go的写法

    错误的写法

    package t9
    
    import (
        "fmt"
        "testing"
    )
    
    
    func TestOutRange(t *testing.T) {
        lst1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
        lst2 := []string{"w", "wg", "wa", "jj", "aa", "ff", "gg", "hh", "asd", "ww", "ee", "gg", "nn", "mm"}
    
        fmt.Println(len(lst1)) // 13
        fmt.Println(len(lst2)) // 14
    
        // 结果
        var retLst1 [][]int
        var retLst2 [][]string
    
        // 超限切片
        for i := 0; i < len(lst1); i += 4 {
            currLst := lst1[i : i+4]
            retLst1 = append(retLst1, currLst)
        }
    
        for i := 0; i < len(lst2); i += 4 {
            currLst := lst2[i : i+4]
            retLst2 = append(retLst2, currLst)
        }
    
    }

    这样写会上报一个错误:

    --- FAIL: TestOutRange (0.00s)
    panic: runtime error: slice bounds out of range [:16] with capacity 13 [recovered]
        panic: runtime error: slice bounds out of range [:16] with capacity 13

    错误的原因是,我们每次获取currLst的时候,是按照 lst[i i+4] 这样直接切片的,但是,如果i+4大于列表lst的长度的话,会上报越界错误!

    正确的写法 ***

    既然i+4可能会超出lst的长度越界,那我们在切片的时候判断一下二者的大小即可:

    package t9
    
    import (
        "fmt"
        "testing"
    )
    
    // 返回两个int最小的那个
    func minInt(a, b int) int {
        if a < b {
            return a
        }
        return b
    }
    
    func TestOutRange(t *testing.T) {
        lst1 := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}
        lst2 := []string{"w", "wg", "wa", "jj", "aa", "ff", "gg", "hh", "asd", "ww", "ee", "gg", "nn", "mm"}
    
        fmt.Println(len(lst1)) // 13
        fmt.Println(len(lst2)) // 14
    
        // 结果
        var retLst1 [][]int
        var retLst2 [][]string
    
        // 切片
        for i := 0; i < len(lst1); i += 4 {
            // 保证不越界
            currLst := lst1[i:minInt(i+4, len(lst1))]
            retLst1 = append(retLst1, currLst)
        }
    
        for i := 0; i < len(lst2); i += 4 {
            // 保证不越界
            currLst := lst2[i:minInt(i+4, len(lst2))]
            retLst2 = append(retLst2, currLst)
        }
    
        // 注意结果有填充的默认值
        fmt.Println(retLst1) // [[1 2 3 4] [5 6 7 8] [9 10 11 12] [13]]
        fmt.Println(retLst2) // [[w wg wa jj] [aa ff gg hh] [asd ww ee gg] [nn mm]]
    }

    ~~~

  • 相关阅读:
    Cognos无法解密来着内容库的用户名和密码凭证
    JavaScript 中的对象引用
    npm install出现的错误
    箭头函数中this的用法
    [译]ArcGIS Server Map Service Cache的组织结构
    [C#] 如何选择抽象基类与接口
    数据库设计规范
    在DataTable中查询应该注意的问题
    坦克大战总结
    仓库管理系统总结(1)
  • 原文地址:https://www.cnblogs.com/paulwhw/p/14205820.html
Copyright © 2011-2022 走看看