首頁 > 軟體

Go語言copy()實現切片複製

2023-04-04 06:01:04

Go語言的內建函數 copy() 可以將一個陣列切片複製到另一個陣列切片中,如果加入的兩個陣列切片不一樣大,就會按照其中較小的那個陣列切片的元素個數進行復制。

copy() 函數的使用格式如下:

copy( destSlice, srcSlice []T) int

其中 srcSlice 為資料來源切片,destSlice 為複製的目標(也就是將 srcSlice 複製到 destSlice),目標切片必須分配過空間且足夠承載複製的元素個數,並且來源和目標的型別必須一致,copy() 函數的返回值表示實際發生複製的元素個數。

下面的程式碼展示了使用 copy() 函數將一個切片複製到另一個切片的過程:

slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice2, slice1) // 只會複製slice1的前3個元素到slice2中
copy(slice1, slice2) // 只會複製slice2的3個元素到slice1的前3個位置

雖然通過迴圈複製切片元素更直接,不過內建的 copy() 函數使用起來更加方便,copy() 函數的第一個引數是要複製的目標 slice,第二個引數是源 slice,兩個 slice 可以共用同一個底層陣列,甚至有重疊也沒有問題。

【範例】通過程式碼演示對切片的參照和複製操作後對切片元素的影響。

package main
import "fmt"
func main() {
    // 設定元素數量為1000
    const elementCount = 1000
    // 預分配足夠多的元素切片
    srcData := make([]int, elementCount)
    // 將切片賦值
    for i := 0; i < elementCount; i++ {
        srcData[i] = i
    }
    // 參照切片資料
    refData := srcData
    // 預分配足夠多的元素切片
    copyData := make([]int, elementCount)
    // 將資料複製到新的切片空間中
    copy(copyData, srcData)
    // 修改原始資料的第一個元素
    srcData[0] = 999
    // 列印參照切片的第一個元素
    fmt.Println(refData[0])
    // 列印複製切片的第一個和最後一個元素
    fmt.Println(copyData[0], copyData[elementCount-1])
    // 複製原始資料從4到6(不包含)
    copy(copyData, srcData[4:6])
    for i := 0; i < 5; i++ {
        fmt.Printf("%d ", copyData[i])
    }
}

程式碼說明如下:

  • 第 8 行,定義元素總量為 1000。
  • 第 11 行,預分配擁有 1000 個元素的整型切片,這個切片將作為原始資料。
  • 第 14~16 行,將 srcData 填充 0~999 的整型值。
  • 第 19 行,將 refData 參照 srcData,切片不會因為等號操作進行元素的複製。
  • 第 22 行,預分配與 srcData 等大(大小相等)、同型別的切片 copyData。
  • 第 24 行,使用 copy() 函數將原始資料複製到 copyData 切片空間中。
  • 第 27 行,修改原始資料的第一個元素為 999。
  • 第 30 行,參照資料的第一個元素將會發生變化。
  • 第 33 行,列印複製資料的首位資料,由於資料是複製的,因此不會發生變化。
  • 第 36 行,將 srcData 的區域性資料複製到 copyData 中。
  • 第 38~40 行,列印複製區域性資料後的 copyData 元素。

補:從切片中刪除元素

package main

import "fmt"


//Go語言並沒有對刪除切片元素提供專用的語法或者介面,需要使用切片本身的特性來刪除元素,
//Go語言中刪除切片元素的本質是,以被刪除元素為分界點,將前後兩個部分的記憶體重新連線起來。
// 根據要刪除元素的位置有三種情況,分別是從開頭位置刪除、從中間位置刪除和從尾部刪除,其中刪除切片尾部的元素速度最快。

func main()  {
    //用=號的話必須先var宣告
    var a [] int
    a=[]int{4,5,6}
    fmt.Println(a)    //[4 5 6]
    //用:=是宣告並賦值,並且系統自動判斷型別,不需要var關鍵字
    b:=[]int{7,8,9}
    fmt.Println(b)  //[7 8 9]

    //1.利用切片的特性來刪除元素
    a=a[1:]  //取索引1以後的值(包含索引1)即刪除a[0]
    //a=a[N:]  //刪除開頭n個元素
    fmt.Println(a)  //[5 6]


    //2.也可以不行動資料指標,但是將後面的資料向開頭移動,可以用 append 原地完成
    // 所謂原地完成是指在原有的切片資料對應的記憶體區間內完成,不會導致記憶體空間結構的變化:
    fmt.Println(a[:0])  //取到a[0]結尾且不包含a[0],即為[]
    a = append(a[:0],a[1:]...)//在尾部追加a[1:],即a[n:]刪除前n個元素
    fmt.Println(a)   //[6]

    //3.copy()函數刪除元素
    //copy把b[1:]複製給b,返回複製後的len(b),多此一舉,和b[1:]結果一樣
    b=b[:copy(b,b[1:])]
    fmt.Println(b)    //[8 9]


    //4.從中間位置刪除
    //對於刪除中間的元素,需要對剩餘的元素進行一次整體挪動,同樣可以用append或copy原地完成


    //append操作
    c:=[]int{1,2,3,4,5}
    //c=append(c[:i],c[i+1:]...)  刪除中間一個元素:(c[i])
    //c=append(c[:i],c[i+N:]...)  刪除中間N個元素:(c[i:I+N-1])
    //先取c[:1]之前的資料,在追加c[2:]之後的資料,即刪除c[1]
    c=append(c[:1],c[2:]...)
    fmt.Println(c) //[1 3 4 5]

    //copy操作
    d:=[]int{1,2,3,4,5}
    //d=d[:i+copy(d[i:],d[i+1:])]  刪除中間一個元素(d[i]),因為從d[i:]開始的,所以i是之前元素的個數
    //d=d[:i+copy(d[i:],d[i+N:])]  刪除中間N個元素

    //先將d[2:]之後的資料copy給d[1:]之後的資料,即刪除了d[1]資料,並返回len(d[2:]),再連線d[1]之前的資料
    d=d[:1+copy(d[1:],d[2:])]   //刪除中間一個元素(d[1])
    fmt.Println(d)//[1 3 4 5]


    //5.從尾部刪除

    g:=[]int{1,2,3,4}
    g=g[:len(g)-1]   //刪除尾部一個元素
    //g=g[:len(g)-N] //刪除尾部N個元素
    fmt.Println(g)   //[1 2 3]


    index()
}


//刪除切片指定位置的元素
func index()  {
    str:=[]string{"a","b","c","d"}
    //指定刪除索引
    index:=2
    //檢視刪除索引之前的元素,刪除索引之後的元素
    fmt.Println(str[:index],str[index+1:])   //[a b] [d]
    //將刪除點前後元素連線起來
    str=append(str[:index],str[index+1:]...)

    fmt.Println(str)   //[a b d]

到此這篇關於Go語言copy()實現切片複製的文章就介紹到這了,更多相關Go 切片複製內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com