গো-তে 2D স্লাইস তৈরির সংক্ষিপ্ত উপায় কী?


108

আমি একটি ট্যুর অফ গো দিয়ে গিয়ে শিখছি । ব্যায়াম এক আমার একটি 2D ফালি তৈরি করতে জিজ্ঞেস dyসারি এবং dxধারণকারী কলাম uint8। আমার বর্তমান পদ্ধতির, যা কাজ করে, এটি হ'ল:

a:= make([][]uint8, dy)       // initialize a slice of dy slices
for i:=0;i<dy;i++ {
    a[i] = make([]uint8, dx)  // initialize a slice of dx unit8 in each of dy slices
}

আমি মনে করি যে এটি শুরু করার জন্য প্রতিটি স্লাইস দ্বারা পুনরাবৃত্তি করা খুব ভার্জোজ। এবং যদি স্লাইসের আরও বেশি মাত্রা থাকে তবে কোডটি অতিরঞ্জিত হয়ে উঠত। গো-তে 2 ডি (বা এন-ডাইমেনশনাল) স্লাইসগুলি সূচনা করার কোনও সংক্ষিপ্ত উপায় আছে?

উত্তর:


160

এর চেয়ে বেশি সংক্ষিপ্ত উপায় নেই, আপনি যা করেছেন তা হ'ল "সঠিক" উপায়; কারণ স্লাইসগুলি সর্বদা এক-মাত্রিক হয় তবে এটি উচ্চতর মাত্রিক অবজেক্টগুলি তৈরির জন্য তৈরি হতে পারে। আরও বিশদের জন্য এই প্রশ্নটি দেখুন: যান: দ্বিমাত্রিক অ্যারের স্মৃতি উপস্থাপনাটি কীভাবে হয়

আপনি এটির একটি জিনিস সহজ করতে পারেন তা হল নির্মাণটি ব্যবহার করা for range:

a := make([][]uint8, dy)
for i := range a {
    a[i] = make([]uint8, dx)
}

আরও মনে রাখবেন যে আপনি যদি আপনার স্লাইসটি একটি যৌগিক আক্ষরিক দিয়ে শুরু করেন তবে আপনি এটি "ফ্রি" এর জন্য পাবেন, উদাহরণস্বরূপ:

a := [][]uint8{
    {0, 1, 2, 3},
    {4, 5, 6, 7},
}
fmt.Println(a) // Output is [[0 1 2 3] [4 5 6 7]]

হ্যাঁ, এর সীমা রয়েছে যেমন আপাতদৃষ্টিতে আপনাকে সমস্ত উপাদানগুলি গণনা করতে হবে; তবে কিছু কৌশল আছে, আপনাকে সমস্ত মান গণনা করতে হবে না, কেবল স্লাইসের উপাদান ধরণের শূন্য মান নয় । এটি সম্পর্কে আরও তথ্যের জন্য গোলং অ্যারে প্রারম্ভিককরণের মূলযুক্ত আইটেমগুলি দেখুন ।

উদাহরণস্বরূপ, যদি আপনি এমন একটি স্লাইস চান যেখানে প্রথম 10 উপাদানগুলি শূন্য হয়, এবং তারপরে অনুসরণ করে 1এবং 2, এটি এটি তৈরি করা যেতে পারে:

b := []uint{10: 1, 2}
fmt.Println(b) // Prints [0 0 0 0 0 0 0 0 0 0 1 2]

আরও মনে রাখবেন যে আপনি যদি টুকরোগুলির পরিবর্তে অ্যারে ব্যবহার করেন তবে এটি খুব সহজেই তৈরি করা যেতে পারে:

c := [5][5]uint8{}
fmt.Println(c)

আউটপুট হল:

[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]

অ্যারেগুলির ক্ষেত্রে আপনাকে "বহিরাগত" অ্যারেতে পুনরাবৃত্তি করতে হবে না এবং "অভ্যন্তরীণ" অ্যারেগুলি আরম্ভ করতে হবে না কারণ অ্যারে বর্ণনাকারী নয় তবে মান রয়েছে। ব্লগ পোস্ট অ্যারে, স্লাইস (এবং স্ট্রিং) দেখুন: আরও তথ্যের জন্য 'অ্যাপেন্ড' এর মেকানিক্স

গো খেলার মাঠে উদাহরণগুলি ব্যবহার করে দেখুন ।


যেহেতু একটি অ্যারে ব্যবহার করা কোডটি সহজতর করে, আমি এটি করতে চাই। কিভাবে একটি স্ট্রাক্ট মধ্যে এটি নির্দিষ্ট করে? আমি পেতে cannot use [5][2]string literal (type [5][2]string) as type [][]string in field valueযখন আমি বললাম কি বললে আমি যেতে বলছি একটি ফালি হয় অ্যারের দায়িত্ব অর্পণ করা চেষ্টা করুন।
এরিক লিন্ডসে

এটি নিজেই বের করেছিলাম এবং তথ্যটি যুক্ত করতে উত্তর সম্পাদনা করেছি।
এরিক লিন্ডসে

4
@ এরিকলিন্ডসে আপনার সম্পাদনাটি ভাল হওয়ার পরেও আমি এটিকে প্রত্যাখ্যান করতে চলেছি কারণ প্রাথমিককরণ সহজ করার কারণে আমি অ্যারের ব্যবহারকে উত্সাহিত করতে চাই না। গো-তে, অ্যারেগুলি গৌণ হয়, টুকরোগুলি হ'ল উপায়। বিশদগুলির জন্য, দেখুন গোতে অন্য একটি অ্যারে সংযুক্ত করার দ্রুততম উপায় কী? অ্যারেগুলির স্থানগুলিও রয়েছে বিশদ জন্য, দেখুন কেন অ্যারে রয়েছে?
আইজজা

যথেষ্ট মোটামুটি, তবে আমি বিশ্বাস করি তথ্যের এখনও যোগ্যতা আছে। আমি আমার সম্পাদনা দিয়ে যা বোঝানোর চেষ্টা করছিলাম সেটি হ'ল যদি আপনার কোনও বস্তুর মধ্যে ভিন্ন ভিন্ন মাত্রার নমনীয়তার প্রয়োজন হয় তবে স্লাইসগুলি যাওয়ার উপায়। অন্যদিকে, যদি আপনার তথ্য কঠোরভাবে কাঠামোগত হয় এবং সর্বদা একই থাকে, তবে অ্যারেগুলি কেবল আরম্ভ করা সহজ নয়, সেগুলি আরও কার্যকর। আমি কীভাবে সম্পাদনাটি উন্নত করতে পারি?
এরিক লিন্ডসে

@ এরিকলিন্ডসে আমি দেখতে পাচ্ছি আপনি অন্য একটি সম্পাদনা করেছেন যা ইতিমধ্যে অন্যরা প্রত্যাখ্যান করেছিল। আপনার সম্পাদনায় আপনি দ্রুত উপাদান অ্যাক্সেস পেতে অ্যারে ব্যবহার করতে বলছিলেন। নোট করুন যে গো অনেকগুলি জিনিসকে অনুকূল করে তোলে এবং এটি এমনটি নাও হতে পারে, টুকরোগুলি ঠিক তত দ্রুত হতে পারে। বিশদ জন্য, অ্যারে বনাম স্লাইস: অ্যাক্সেস গতি দেখুন
আইজজা

12

ম্যাট্রিক্স তৈরি করতে দুটি টুকরো ব্যবহার করার উপায় রয়েছে। আসুন তাদের মধ্যে পার্থক্য একবার দেখে নেওয়া যাক।

প্রথম পদ্ধতি:

matrix := make([][]int, n)
for i := 0; i < n; i++ {
    matrix[i] = make([]int, m)
}

দ্বিতীয় পদ্ধতি:

matrix := make([][]int, n)
rows := make([]int, n*m)
for i := 0; i < n; i++ {
    matrix[i] = rows[i*m : (i+1)*m]
}

প্রথম পদ্ধতির ক্ষেত্রে, ধারাবাহিক makeকল করা নিশ্চিত করে না যে আপনি একটি ম্যাট্রিক্সের সাথে মিল রেখেছেন, সুতরাং আপনার ম্যাট্রিক্স মেমরির মধ্যে বিভক্ত থাকতে পারে। আসুন দুটি গো রুটিনের সাথে একটি উদাহরণ চিন্তা করি যা এর কারণ হতে পারে:

  1. রুটিন # 0 এর make([][]int, n)জন্য বরাদ্দ মেমরি পেতে matrix0x000 থেকে 0x07F মেমরি পেয়ে যায়।
  2. তারপরে, এটি লুপটি শুরু করে এবং প্রথম সারিতে make([]int, m)0x080 থেকে 0x0FF এ চলে।
  3. দ্বিতীয় পুনরাবৃত্তিতে এটি শিডিয়ুলার দ্বারা পরাস্ত হয়।
  4. সিডিউলার প্রসেসরটিকে রুটিন # 1 এ দেয় এবং এটি চলমান শুরু করে। এটি একটি make(নিজস্ব উদ্দেশ্যে) ব্যবহার করে এবং 0x100 থেকে 0x17F এ চলে যায় (রুটিন # 0 এর প্রথম সারির ঠিক পাশে)।
  5. কিছুক্ষণ পরে, এটি পলিত হয় এবং রুটিন # 0 আবার চলতে শুরু করে।
  6. এটি make([]int, m)দ্বিতীয় লুপ পুনরাবৃত্তির সাথে সম্পর্কিত এবং দ্বিতীয় সারির জন্য 0x180 থেকে 0x1FF এ চলে। এই মুহুর্তে, আমরা ইতিমধ্যে দুটি বিভক্ত সারি পেয়েছি।

দ্বিতীয় পদ্ধতিটির সাথে, রুটিনটি make([]int, n*m)একক টুকরোতে সমস্ত ম্যাট্রিক্স বরাদ্দ পাওয়ার জন্য, সাবলীলতা নিশ্চিত করে। এর পরে, প্রতিটি সারির সাথে সাবস্ক্রাইবগুলিতে ম্যাট্রিক্স পয়েন্টার আপডেট করার জন্য একটি লুপ প্রয়োজন।

উভয় পদ্ধতি ব্যবহার করে নির্ধারিত মেমরির পার্থক্য দেখতে আপনি গো প্লেগ্রাউন্ডে উপরে প্রদর্শিত কোডটি খেলতে পারেন । নোট করুন যে আমি runtime.Gosched()কেবলমাত্র প্রসেসরের ফলন এবং শিডিয়ুলারকে অন্য একটি রুটিনে স্যুইচ করতে বাধ্য করার উদ্দেশ্যে ব্যবহার করেছি ।

কোনটি ব্যবহার করবেন? প্রথম পদ্ধতির সাথে সবচেয়ে খারাপ পরিস্থিতিটি কল্পনা করুন, অর্থাত প্রতিটি সারি মেমোরিতে অন্য সারিতে নয়। তারপরে, যদি ম্যাট্রিক্স উপাদানগুলির (যদি সেগুলি পড়তে বা লেখার জন্য) আপনার প্রোগ্রামটি পুনরাবৃত্তি করে তবে খারাপ ডেটার লোকালতার কারণে সম্ভবত দ্বিতীয় পদ্ধতির তুলনায় আরও ক্যাশে মিস (সম্ভবত উচ্চতর বিলম্বিতা) থাকবে। অন্যদিকে, দ্বিতীয় পদ্ধতির সাহায্যে ম্যাট্রিক্সের জন্য বরাদ্দকৃত একটি মেমরি পাওয়া সম্ভব নয়, কারণ মেমরি বিভাজন (সমস্ত স্মৃতিতে ছড়িয়ে পড়ে), তাত্ত্বিকভাবে এটির জন্য পর্যাপ্ত ফ্রি মেমরি থাকতে পারে ।

অতএব, যদি না প্রচুর পরিমাণে মেমরি বিভাজন ঘটে এবং ম্যাট্রিক্স বরাদ্দ করা যথেষ্ট পরিমাণে না হয়, আপনি ডেটা লোকালটির সুবিধা পেতে সর্বদা দ্বিতীয় পদ্ধতিটি ব্যবহার করতে চাইবেন।


4
golang.org/doc/effective_go.html# স্লাইসগুলি স্লাইস-নেটিভ সিনট্যাক্সের (যেমন i i 1) * মি এর মত স্পষ্টভাবে স্লাইস সীমানা গণনা করার প্রয়োজন নেই - স্বতন্ত্র মেমরি কৌশলটি করার চতুর উপায়টি দেখায়
ম্যাগনাস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.