গোতে দুটি টুকরো সংঘবদ্ধ করুন


476

আমি স্লাইস [1, 2]এবং স্লাইস একত্রিত করার চেষ্টা করছি [3, 4]। আমি কীভাবে এই কাজটি করতে পারি?

আমি চেষ্টা করেছিলাম:

append([]int{1,2}, []int{3,4})

কিন্তু পেয়েছি:

cannot use []int literal (type []int) as type int in append

যাইহোক, ডকুমেন্টেশনগুলি ইঙ্গিত দেয় যে এটি সম্ভব, আমি কী অনুপস্থিত?

slice = append(slice, anotherSlice...)

উত্তর:


874

দ্বিতীয় স্লাইসের পরে বিন্দু যুক্ত করুন:

//---------------------------vvv
append([]int{1,2}, []int{3,4}...)

এটি অন্য যে কোনও ভ্যারিয়েডিক ফাংশনের মতোই।

func foo(is ...int) {
    for i := 0; i < len(is); i++ {
        fmt.Println(is[i])
    }
}

func main() {
    foo([]int{9,8,7,6,5}...)
}

37
append()একটি ভেরিয়াদিক ফাংশন, এবং ...আপনাকে একটি স্লাইস থেকে ভেরিয়াদিক ফাংশনে একাধিক যুক্তি দেয়।

11
টুকরোগুলি বেশ বড় হলে এই কি পারফরম্যান্ট হয়? অথবা সংকলকটি সত্যই সমস্ত উপাদানগুলিকে পরামিতি হিসাবে পাস করে না?
টোড

15
@ টোড: এটি আসলে এগুলি ছড়িয়ে দেয় না। ইন foo()উপরোক্ত উদাহরণে, isপরামিতি মূল ফালি, যা এটি একই অন্তর্নিহিত এরে, lên এবং টুপি আলো-ওজন রেফারেন্স একটি কপি আছে বলতে হয় একটি কপি ঝুলিতে। যদি fooফাংশনটি কোনও সদস্যকে পরিবর্তন করে, তবে পরিবর্তনটি মূলটিতে দেখা যাবে। এখানে একটি ডেমো রয়েছে । সুতরাং একমাত্র আসল ওভারহেডটি হ'ল এটি যদি আপনার ইতিমধ্যে একটি না থাকে তবে এটি foo(1, 2, 3, 4, 5)একটি নতুন স্লাইস তৈরি করে : যেমন: এটি একটি নতুন স্লাইস তৈরি করবে যা isধারণ করবে।

2
আহ। যদি আমি সঠিকভাবে বুঝতে পারি, বৈকল্পিক ফাংশনটি আসলে প্যারামিটারের অ্যারের মতো প্রয়োগ করা হয় (স্ট্যাকের প্রতিটি প্যারামিটারের পরিবর্তে)? এবং যেহেতু আপনি স্লাইসে পাস করেছেন, এটি আসলে একের উপর একটি মানচিত্র করে?
টোড

@ টোড: হ্যাঁ, আপনি যখন ...কোনও বিদ্যমান স্লাইস ব্যবহার করেন, এটি কেবল সেই স্লাইসটি পাস করে। আপনি যখন পৃথক যুক্তিগুলি পাস করেন, এটি তাদের একটি নতুন টুকরোতে সংগ্রহ করে এবং তা পাস করে। আমি সঠিক বলবিজ্ঞান সরাসরি জ্ঞান নেই, কিন্তু আমি অনুমান চাই যে এই: foo(1, 2, 3, 4, 5)এবং এই: func foo(is ...int) {এই মাত্র ডি চিনি: foo([]int{1, 2, 3, 4, 5})এবং এই: func foo(is []int) {

77

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

Variadic ফাংশন appendশূন্য বা তার বেশি মান appends xকরার s ধরণ S, যা একটি ফালি টাইপ হতে হবে, এবং তার ফলে ছে ফেরৎ, এছাড়াও ধরনের S। মানগুলি xটাইপের একটি প্যারামিটারে প্রেরণ করা হয় ...Tযেখানে Tএলিমেন্টের ধরণ রয়েছে Sএবং সংশ্লিষ্ট পরামিতি উত্তীর্ণের বিধিগুলি প্রয়োগ হয়। একটি বিশেষ কেস হিসাবে, অ্যাপেন্ড অনুসরণ করে টাইপের []byteদ্বিতীয় যুক্তির সাথে টাইপ করার জন্য নির্ধারিত প্রথম যুক্তিটি গ্রহণ stringকরে ...। এই ফর্মটি স্ট্রিংয়ের বাইটগুলি সংযোজন করে।

append(s S, x ...T) S  // T is the element type of S

s0 := []int{0, 0}
s1 := append(s0, 2)        // append a single element     s1 == []int{0, 0, 2}
s2 := append(s1, 3, 5, 7)  // append multiple elements    s2 == []int{0, 0, 2, 3, 5, 7}
s3 := append(s2, s0...)    // append a slice              s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}

... পরামিতিগুলিতে যুক্তিগুলি পাস করা

যদি fচূড়ান্ত পরামিতি প্রকারের সাথে বৈকল্পিক হয় ...Tতবে ফাংশনের মধ্যে যুক্তিটি টাইপের পরামিতির সমতুল্য []T। প্রতিটি কল এ f, চূড়ান্ত প্যারামিটারে যুক্ত হওয়া আর্গুমেন্টটি টাইপের একটি নতুন স্লাইস []Tযার ধারাবাহিক উপাদানগুলি হ'ল আসল আর্গুমেন্ট, যা সকলকে অবশ্যই টাইপের জন্য নির্ধারিত হতে হবে T। স্লাইসের দৈর্ঘ্য হ'ল চূড়ান্ত প্যারামিটারে আবদ্ধ আর্গুমেন্টের সংখ্যা এবং প্রতিটি কল সাইটের জন্য পৃথক হতে পারে।

আপনার প্রশ্নের উত্তর উদাহরণ s3 := append(s2, s0...)মধ্যে যান প্রোগ্রামিং ভাষা নির্দিষ্টকরণ । উদাহরণ স্বরূপ,

s := append([]int{1, 2}, []int{3, 4}...)

6
দ্রষ্টব্য: অ্যাপেন্ডের সাধারণ ব্যবহার (স্লাইস 1, স্লাইস 2 ...) আমার কাছে বেশ বিপজ্জনক বলে মনে হচ্ছে। যদি স্লাইস 1 বৃহত্তর অ্যারের একটি স্লাইস হয় তবে সেই অ্যারের মানগুলি স্লাইস 2 দ্বারা ওভাররাইট করা হবে। (এটি আমাকে ক্রিঞ্জ করে তোলে যে এটি সাধারণ উদ্বেগ বলে মনে হচ্ছে না?)
হুগো

7
@ হুগো আপনি যদি আপনার অ্যারের কোনও স্লাইসের উপরে "হাত" দেন, তবে জেনে রাখুন যে স্লাইস "মালিক" স্লাইসের বর্তমান দৈর্ঘ্যের বাইরে থাকা অ্যারের অংশগুলি দেখতে / ওভাররাইট করতে সক্ষম হবে। আপনি যদি এটি না চান তবে আপনি একটি সম্পূর্ণ স্লাইস এক্সপ্রেশন ব্যবহার করতে পারেন (আকারে a[low : high : max]) যা সর্বোচ্চ ক্ষমতাও নির্দিষ্ট করে । উদাহরণস্বরূপ স্লাইসের a[0:2:4]ধারণক্ষমতা থাকবে 4এবং এটির বাইরে উপাদানগুলি অন্তর্ভুক্ত করার জন্য এটি প্রতিস্থাপন করা যাবে না, এমনকি ব্যাকিং অ্যারে এর পরেও হাজার উপাদান রয়েছে কিনা।
আইকজা

30

অন্যান্য উত্তরের বিপরীতে কিছুই না, তবে ডক্সে সংক্ষেপে আমি এর উদাহরণগুলির চেয়ে আরও সহজে বোধগম্য হতে পেলাম :

func সংযোজন

func append(slice []Type, elems ...Type) []Typeঅন্তর্ভুক্ত অন্তর্ভুক্ত ফাংশন একটি স্লাইসের শেষে উপাদানগুলিকে সংযোজন করে। যদি এটির পর্যাপ্ত ক্ষমতা থাকে তবে নতুন উপাদানগুলির জন্য গন্তব্যটিকে পুনরায় স্থান দেওয়া হয়। যদি এটি না হয় তবে একটি নতুন অন্তর্নিহিত অ্যারে বরাদ্দ করা হবে। সংযোজন আপডেট স্লাইস প্রদান করে। সুতরাং প্রায়শই স্লাইসটি ধারণ করে চলকটিতে অ্যাপিডের ফলাফল সংরক্ষণ করা প্রয়োজন:

slice = append(slice, elem1, elem2)
slice = append(slice, anotherSlice...)

একটি বিশেষ কেস হিসাবে, বাইট স্লাইসে একটি স্ট্রিং যুক্ত করা আইনী:

slice = append([]byte("hello "), "world"...)

1
ধন্যবাদ! আমার জন্য মূল্যবান!
কোরজাভিন ইভান

23

আমি মনে করি এবং এটি জেনে রাখা গুরুত্বপূর্ণ যে আপনি যদি গন্তব্য স্লাইস (আপনি যে স্লাইসটি সংযোজন করেন) এর যথেষ্ট ক্ষমতা থাকে তবে গন্তব্যটিকে বিশ্লেষণ করে (স্থানটি তার স্থানে বৃদ্ধি করার লক্ষ্যে সংলগ্নকরণ) সংযোজন দ্বারা "স্থান" হয়ে যাবে সংযোজনযোগ্য উপাদান সমন্বয় করতে সক্ষম)।

এর অর্থ হ'ল যদি গন্তব্যটি বৃহত অ্যারে বা টুকরো টুকরো করে তৈরি করা হয়েছিল যার ফলস্বরূপ স্লাইসের দৈর্ঘ্যের বাইরে অতিরিক্ত উপাদান রয়েছে তবে তারা ওভাররাইট হয়ে যেতে পারে।

প্রদর্শনের জন্য, এই উদাহরণটি দেখুন:

a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)

x, y := a[:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))

x = append(x, y...)
fmt.Printf("x: %v\n", x)

fmt.Printf("a: %v\n", a)

আউটপুট ( গো খেলার মাঠে এটি চেষ্টা করুন ):

a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 10
x: [1 2 3 4]
a: [1 2 3 4 0 0 0 0 0 0]

aদৈর্ঘ্য সহ আমরা একটি "ব্যাকিং" অ্যারে তৈরি করেছি 10। তারপরে আমরা xএই aঅ্যারেটি কেটে গন্তব্য স্লাইস তৈরি করি , yসংমিশ্রিত আক্ষরিক ব্যবহার করে স্লাইস তৈরি করা হয় []int{3, 4}। এখন যখন আমরা যোগ yকরতে x, ফলে প্রত্যাশিত হয় [1 2 3 4], কিন্তু কি বিস্ময়কর যেতে পারে যে ব্যাকিং অ্যারে aএটাও একটা কারণ ক্ষমতা পরিবর্তন xহয় 10যা যথেষ্ট সংযোজন করতে yএটি, তাই xresliced যা একই ব্যবহার করবে aব্যাকিং অ্যারে, এবং সেখানে append()উপাদান অনুলিপি yকরা হবে।

আপনি এই এড়াতে চান, তাহলে আপনি একটি ব্যবহার করতে পারেন সম্পূর্ণ ফালি অভিব্যক্তি যা ফর্ম আছে

a[low : high : max]

যা একটি স্লাইস তৈরি করে এবং এটিকে সেট করে ফলাফলের স্লাইসের ক্ষমতা নিয়ন্ত্রণ করে max - low

পরিবর্তিত উদাহরণ দেখুন (শুধুমাত্র পার্থক্য আমরা তৈরি করে xভালো: x = a[:2:2]:

a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)

x, y := a[:2:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))

x = append(x, y...)
fmt.Printf("x: %v\n", x)

fmt.Printf("a: %v\n", a)

আউটপুট ( গো খেলার মাঠে এটি চেষ্টা করুন )

a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 2
x: [1 2 3 4]
a: [1 2 0 0 0 0 0 0 0 0]

আপনি দেখতে পাচ্ছেন, আমরা একই xফল পেয়েছি তবে ব্যাকিং অ্যারে aপরিবর্তন হয়নি, কারণ ক্ষমতা x"কেবল" ছিল 2(সম্পূর্ণ স্লাইস এক্সপ্রেশনকে ধন্যবাদ a[:2:2])। সুতরাং সংযোজনটি করতে, একটি নতুন ব্যাকিং অ্যারে বরাদ্দ করা হয়েছে যা উভয়ের উপাদান সংরক্ষণ করতে পারে xএবং yযা পৃথক a


2
আমি যে সমস্যার মুখোমুখি হচ্ছি এটি খুব সহায়ক। ধন্যবাদ।
এইড

9

আমি @ আইকজা উত্তরের উপর জোর দিতে এবং এটি কিছুটা সহজ করতে চাই কারণ এটি একটি গুরুত্বপূর্ণ ধারণা। আমি ধরে নিই যে পাঠক টুকরোগুলির সাথে পরিচিত ।

c := append(a, b...)

এটি প্রশ্নের বৈধ উত্তর is তবে যদি আপনাকে পরে বিভিন্ন প্রসঙ্গে কোডে 'এ' এবং 'সি' টুকরোগুলি ব্যবহার করার প্রয়োজন হয় তবে এটি স্লাইসগুলি সংযুক্ত করার নিরাপদ উপায় নয়।

ব্যাখ্যা করতে, এক্সপ্রেশনটি স্লাইসের ক্ষেত্রে নয়, তবে অন্তর্নিহিত অ্যারেগুলির শর্তে পড়তে দিন:

"'ক' এর অ্যারে নিন (অন্তর্নিহিত) এবং অ্যারে 'বি' থেকে উপাদানগুলি এতে যুক্ত করুন ar অ্যারে 'ক' এর 'বি' থেকে সমস্ত উপাদান অন্তর্ভুক্ত করার যথেষ্ট ক্ষমতা রয়েছে - 'গ' এর অন্তর্নিহিত অ্যারে নতুন অ্যারে হবে না , এটি আসলে অ্যারে 'এ' হবে ically মূলত, স্লাইস 'এ' অন্তর্নিহিত অ্যারে 'ক' এর উপাদানগুলি লেন (ক) প্রদর্শন করবে এবং 'গ' স্লাইস 'সি' অ্যারের 'ল' (সি) প্রদর্শন করবে ""

সংযোজন () অগত্যা একটি নতুন অ্যারে তৈরি করে না! এটি অপ্রত্যাশিত ফলাফল হতে পারে। দেখুন যান খেলার মাঠ উদাহরণ

আপনি যদি নিশ্চিত করতে চান যে স্লাইসের জন্য নতুন অ্যারে বরাদ্দ করা হয়েছে তবে সর্বদা মেক () ফাংশনটি ব্যবহার করুন। উদাহরণস্বরূপ, এখানে কাজের জন্য কুরুচিপূর্ণ তবে দক্ষ পর্যাপ্ত বিকল্প রয়েছে।

la := len(a)
c := make([]int, la, la + len(b))
_ = copy(c, a)
c = append(c, b...)

la := len(a)
c := make([]int, la + len(b))
_ = copy(c, a)
_ = copy(c[la:], b)

এই পার্শ্ব প্রতিক্রিয়াগুলি নির্দেশ করার জন্য ধন্যবাদ। আশ্চর্যজনকভাবে এই পরিবর্তিত জেনেরিওর সাথে পৃথক। play.golang.org/p/9FKo5idLBj4 অতিরিক্ত ক্ষমতা সরবরাহ করার সময়, কারও সাবধানতার সাথে কল্পনাযোগ্য অন্তর্দৃষ্টি বিরুদ্ধে এই বিস্ময়কর পার্শ্ব প্রতিক্রিয়া সম্পর্কে চিন্তা করা উচিত।
অলিপুনার

5

অ্যাপেন্ড () ফাংশন এবং স্প্রেড অপারেটর

দুটি appendস্ট্রাইস স্ট্যান্ডার্ড গোলং লাইব্রেরিতে পদ্ধতি ব্যবহার করে জড়িত করা যেতে পারে । যা variadicফাংশন অপারেশনের অনুরূপ । সুতরাং আমাদের ব্যবহার করা প্রয়োজন...

package main

import (
    "fmt"
)

func main() {
    x := []int{1, 2, 3}
    y := []int{4, 5, 6}
    z := append([]int{}, append(x, y...)...)
    fmt.Println(z)
}

উপরের কোডটির আউটপুট: [1 2 3 4 5 6]


2

append([]int{1,2}, []int{3,4}...)কাজ করবে. ...পরামিতিগুলিতে যুক্তিগুলি পাস করা।

যদি টাইপের fচূড়ান্ত প্যারামিটারের সাথে বৈকল্পিক হয় তবে প্রকারের মধ্যে টাইপের সমতুল্য ।p...Tfp[]T

যদি এর fজন্য কোনও আসল আর্গুমেন্ট না দিয়ে আবেদন করা হয় pতবে মানটি উত্তীর্ণ pহয় nil

অন্যথায়, পাস করা মান হ'ল একটি নতুন []Tঅন্তর্নিহিত অ্যারের সাথে টাইপের একটি নতুন স্লাইস যার ধারাবাহিক উপাদানগুলি হ'ল আসল যুক্তি, যা সকলকে অবশ্যই নির্ধারিত হতে হবে T। স্লাইসের দৈর্ঘ্য এবং ক্ষমতা হ'ল pপ্রতিটি কল সাইটের জন্য আবদ্ধ আর্গুমেন্টের সংখ্যা এবং আলাদা হতে পারে।

ফাংশন এবং কল দেওয়া হয়েছে

func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:", "Joe", "Anna", "Eileen")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.