আমি কেন `অনুলিপি () with দিয়ে একটি স্লাইস নকল করতে পারি না?


121

আমাকে গোতে একটি স্লাইসের একটি অনুলিপি তৈরি করতে হবে এবং ডকসটি পড়তে হবে আমার নিষ্পত্তি করার জন্য একটি অনুলিপি ফাংশন।

অনুলিপিটি অন্তর্নির্মিত ফাংশন একটি উত্স স্লাইস থেকে উপাদানগুলি একটি গন্তব্য স্লাইসে অনুলিপি করে। (একটি বিশেষ কেস হিসাবে, এটি একটি স্ট্রিং থেকে বাইটের স্লাইসে বাইটগুলি অনুলিপি করবে)) উত্স এবং গন্তব্যটি ওভারল্যাপ হতে পারে। অনুলিপি অনুলিপি করা উপাদানগুলির সংখ্যা প্রদান করে, যা সর্বনিম্ন লেন (এসসিআর) এবং লেন (ডিএসটি) হবে।

কিন্তু যখন আমি করি:

arr := []int{1, 2, 3}
tmp := []int{}
copy(tmp, arr)
fmt.Println(tmp)
fmt.Println(arr)

আমার tmpআগের মতো শূন্য (আমি ব্যবহারের চেষ্টাও করেছি arr, tmp):

[]
[1 2 3]

আপনি গো খেলার মাঠে এটি পরীক্ষা করতে পারেন । তাহলে আমি কেন একটি টুকরো অনুলিপি করতে পারি না?


সবাইকে ধন্যবাদ, এটি সত্যিই দুঃখজনক যে আমি খেয়াল করি নি যে টুকরো একই দৈর্ঘ্য হওয়া উচিত।
সালভাদোর ডালি

1
অগত্যা একই নয়, তবে dstআপনি অনুলিপি করতে চান এমন অনেকগুলি উপাদান অন্তত বড় হওয়া উচিত (এর সম্পূর্ণ অনুলিপিটির srcঅর্থ len(dst) >= len(src))।
আইকজা

2
b := append([]int{}, a...)
রকেটস্পেসার

উত্তর:


209

অন্তর্নির্মিত উপাদানগুলি copy(dst, src)অনুলিপি min(len(dst), len(src))করে।

সুতরাং আপনার dstযদি খালি থাকে ( len(dst) == 0), কোনও কিছুই অনুলিপি করা হবে না।

চেষ্টা করুন tmp := make([]int, len(arr))( খেলার মাঠে যান ):

arr := []int{1, 2, 3}
tmp := make([]int, len(arr))
copy(tmp, arr)
fmt.Println(tmp)
fmt.Println(arr)

আউটপুট (আশানুরূপ হিসাবে):

[1 2 3]
[1 2 3]

দুর্ভাগ্যক্রমে এটি builtinপ্যাকেজে নথিভুক্ত করা হয়নি , তবে এটি গো ল্যাঙ্গুয়েজ স্পেসিফিকেশনে নথিবদ্ধ করা হয়েছে : টুকরাগুলিতে সংযোজন এবং অনুলিপি করা :

অনুলিপি করা উপাদানগুলির সংখ্যা সর্বনিম্ন len(src)এবং len(dst)

সম্পাদনা:

অবশেষে এর ডকুমেন্টেশন copy()আপডেট করা হয়েছে এবং এটিতে এখন উত্স এবং গন্তব্যের ন্যূনতম দৈর্ঘ্য অনুলিপি করা হবে তা উপস্থিত রয়েছে:

অনুলিপি অনুলিপি করা উপাদানগুলির সংখ্যা প্রদান করে, যা সর্বনিম্ন লেন (এসসিআর) এবং লেন (ডিএসটি) হবে।


2
সংক্ষেপে বলা যায়, copyগন্তব্য স্লাইস খুব ছোট হলে গন্তব্য স্লাইস বাড়ানোর পক্ষে যুক্তি ধারণ করে না, তবে আরও একটি বিল্ট-ইন ফাংশন রয়েছে যা করে: append এই উদাহরণে ডান আকারের স্লাইসটি প্রথম স্থানে বরাদ্দ করা ভাল, appendআপনি ইতিমধ্যে একটি স্লাইস এবং শেষ পর্যন্ত উপাদান যোগ করে এটি বৃদ্ধি করতে চাইলে ব্যবহার করা যেতে পারে।
থোমাসরুটটার

1
তবে আনবাউন্ডেড মাপের স্লাইসটি অনুলিপি করার সময় কেন আমাকে বাউন্ডেড সাইজের স্লাইস তৈরি করতে হবে?
অ্যালেক্স

24

এটি করার আরেকটি সহজ উপায় হ'ল ব্যবহার করে appendযা প্রক্রিয়াটিতে স্লাইস বরাদ্দ করবে।

arr := []int{1, 2, 3}
tmp := append([]int(nil), arr...)  // Notice the ... splat
fmt.Println(tmp)
fmt.Println(arr)

আউটপুট (আশানুরূপ হিসাবে):

[1 2 3]
[1 2 3]

সুতরাং অ্যারে অনুলিপি করার জন্য একটি সংক্ষিপ্ত বিবরণ arrহবেappend([]int(nil), arr...)

https://play.golang.org/p/sr_4ofs5GW


8
এখানে ধরাটি হ'ল বাস্তব-জগতের উদাহরণগুলিতে, যা অনেক বেশি বড়, অ্যাপেন্ড অতিরিক্ত মেমরি বরাদ্দ করবে - যদি না এই অ্যারেটি আরও কিছু প্রক্রিয়াজাতকরণের পরে পরে ক্ষমতায় পূর্ণ হয় - কারণ এটি বারবার কলগুলির উপর দক্ষ পুনঃনির্ধারণের জন্য ডিজাইন করা হয়েছে। play.golang.org/p/5_6618xnXn পর্যবেক্ষণ করুন যে ক্যাপ (এক্স) 12-এ বেড়েছে, 10 নয় now এখন দেখুন কী ঘটে যখন 1 মান 1048576 মানগুলিতে যুক্ত হয় play.golang.org/p/nz32JPhhl 2048 স্লট দ্বারা ক্ষমতা বাড়িয়ে তোলে 1050624, শুধুমাত্র একটি অতিরিক্ত মান সমন্বিত করতে।
জে। অ্যান্ড্রু শুস্তা

12

যদি আপনার স্লাইসগুলি একই আকারের হয় তবে এটি কাজ করবে :

arr := []int{1, 2, 3}
tmp := []int{0, 0, 0}
i := copy(tmp, arr)
fmt.Println(i)
fmt.Println(tmp)
fmt.Println(arr)

দিতে হবে:

3
[1 2 3]
[1 2 3]

" গো টুকরো: ব্যবহার এবং অভ্যন্তরীণ " থেকে:

অনুলিপি ফাংশনটি বিভিন্ন দৈর্ঘ্যের টুকরোগুলির মধ্যে অনুলিপি সমর্থন করে ( এটি কেবলমাত্র অল্প সংখ্যক উপাদান পর্যন্ত অনুলিপি করবে )

সাধারণ উদাহরণটি হ'ল:

t := make([]byte, len(s), (cap(s)+1)*2)
copy(t, s)
s = t

10

অনুলিপিটি dst এবং src এর সর্বনিম্ন দৈর্ঘ্যের জন্য চালিত হয়, তাই আপনাকে অবশ্যই পছন্দসই দৈর্ঘ্যে ডিএসটি শুরু করতে হবে।

A := []int{1, 2, 3}
B := make([]int, 3)
copy(B, A)
C := make([]int, 2)
copy(C, A)
fmt.Println(A, B, C)

আউটপুট:

[1 2 3] [1 2 3] [1 2]

আপনি শিলার টুকরোতে অ্যাপেনড () ব্যবহার করে সমস্ত উপাদানকে এক লাইনে আরম্ভ এবং অনুলিপি করতে পারেন।

x := append([]T{}, []...)

উদাহরণ:

A := []int{1, 2, 3}
B := append([]int{}, A...)
C := append([]int{}, A[:2]...)
fmt.Println(A, B, C)    

আউটপুট:

[1 2 3] [1 2 3] [1 2]

বরাদ্দ + অনুলিপি () এর সাথে তুলনা করে 1000 টিরও বেশি উপাদানের জন্য অ্যাপেন্ড ব্যবহার করুন। প্রকৃতপক্ষে 1,000 পার্থক্যটি উপেক্ষিত হতে পারে, আপনার যদি অনেকগুলি টুকরো না থাকে তবে এটিকে থাম্বের নিয়মের জন্য যান।

BenchmarkCopy1-4                50000000            27.0 ns/op
BenchmarkCopy10-4               30000000            53.3 ns/op
BenchmarkCopy100-4              10000000           229 ns/op
BenchmarkCopy1000-4              1000000          1942 ns/op
BenchmarkCopy10000-4              100000         18009 ns/op
BenchmarkCopy100000-4              10000        220113 ns/op
BenchmarkCopy1000000-4              1000       2028157 ns/op
BenchmarkCopy10000000-4              100      15323924 ns/op
BenchmarkCopy100000000-4               1    1200488116 ns/op
BenchmarkAppend1-4              50000000            34.2 ns/op
BenchmarkAppend10-4             20000000            60.0 ns/op
BenchmarkAppend100-4             5000000           240 ns/op
BenchmarkAppend1000-4            1000000          1832 ns/op
BenchmarkAppend10000-4            100000         13378 ns/op
BenchmarkAppend100000-4            10000        142397 ns/op
BenchmarkAppend1000000-4            2000       1053891 ns/op
BenchmarkAppend10000000-4            200       9500541 ns/op
BenchmarkAppend100000000-4            20     176361861 ns/op

1
বারবার কল করে অ্যারে বৃদ্ধি হবে এমন ক্ষেত্রে অ্যাপেন্ড ব্যবহার করা উচিত, কারণ এটি প্রত্যাশায় অতিরিক্ত ক্ষমতা বরাদ্দ করবে। ফলাফলের অ্যারেটি সঠিক আকারে তৈরি করা উচিত এবং পুনরায় পুনরায় স্থানান্তরিত হয় না এমন ক্ষেত্রে প্রতি প্রতি ইনপুট অ্যারে অনুলিপি ব্যবহার করা উচিত। play.golang.org/p/0kviwKmGzx আপনি সেই মানদণ্ডের কোডটি ভাগ করেন নি যা ফলাফলগুলি তৈরি করেছে যাতে আমি এর বৈধতা নিশ্চিত করতে বা অস্বীকার করতে পারি না, তবে এটি আরও গুরুত্বপূর্ণ বিষয়টিকে উপেক্ষা করে।
জে। অ্যান্ড্রু shusta

1
আপনার অর্থ 'স্লাইস' অ্যারে নয় । তারা বিভিন্ন জিনিস।
Inanc Gumus

2

গো প্রোগ্রামিং ভাষার স্পেসিফিকেশন

টুকরাগুলিতে সংযোজন এবং অনুলিপি করা

ফাংশন অনুলিপি উত্স src থেকে একটি গন্তব্য ডিস্টে উপাদানগুলি স্লাইস করে এবং অনুলিপি করা উপাদানগুলির সংখ্যা প্রদান করে। উভয় আর্গুমেন্টে অবশ্যই অভিন্ন উপাদান টাইপ টি থাকতে হবে এবং অবশ্যই [] টি প্রকারের একটি স্লাইনে নির্দিষ্ট করতে হবে। অনুলিপি করা উপাদানগুলির সংখ্যা হ'ল ন্যূনতম (এসসিআর) এবং লেন (ডিএসটি)। একটি বিশেষ কেস হিসাবে, অনুলিপি একটি স্ট্রিং টাইপের উত্স আর্গুমেন্ট সহ [] বাইট টাইপ করার জন্য নির্ধারিত একটি গন্তব্য যুক্তি গ্রহণ করে। এই ফর্মটি স্ট্রিং থেকে বাইটগুলি বাইট স্লাইসে অনুলিপি করে।

copy(dst, src []T) int
copy(dst []byte, src string) int

tmpজন্য পর্যাপ্ত জায়গা প্রয়োজন arr। উদাহরণ স্বরূপ,

package main

import "fmt"

func main() {
    arr := []int{1, 2, 3}
    tmp := make([]int, len(arr))
    copy(tmp, arr)
    fmt.Println(tmp)
    fmt.Println(arr)
}

আউটপুট:

[1 2 3]
[1 2 3]

0

এখানে একটি স্লাইস অনুলিপি করার উপায় is আমি কিছুটা দেরি করেছি, তবে @ ডেভের চেয়ে আরও সহজ এবং দ্রুত উত্তর রয়েছে। এটি @ ডেভের মতো কোড থেকে উত্পন্ন নির্দেশাবলী। এই আমার দ্বারা উত্পাদিত নির্দেশাবলী। আপনি দেখতে পাচ্ছেন যে এখানে অনেক কম নির্দেশ রয়েছে। যা হয় তা কেবল এটি করে append(slice), যা স্লাইসটি অনুলিপি করে। এই কোড:

package main

import "fmt"

func main() {
    var foo = []int{1, 2, 3, 4, 5}
    fmt.Println("foo:", foo)
    var bar = append(foo)
    fmt.Println("bar:", bar)
    bar = append(bar, 6)
    fmt.Println("foo after:", foo)
    fmt.Println("bar after:", bar)
}

এটি ফলাফল:

foo: [1 2 3 4 5]
bar: [1 2 3 4 5]
foo after: [1 2 3 4 5]
bar after: [1 2 3 4 5 6]
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.