বিদ্যমান অ্যারে থেকে সাব-অ্যারে নেওয়া


335

আমার কাছে 10 টি উপাদানের অ্যারে এক্স রয়েছে। আমি এক্স থেকে সমস্ত উপাদান যুক্ত একটি নতুন অ্যারে তৈরি করতে চাই যা সূচক 3 থেকে শুরু হয় এবং সূচক 7 এ শেষ হয় অবশ্যই আমি সহজেই একটি লুপ লিখতে পারি যা এটি আমার জন্য করবে তবে আমি আমার কোডটি যতটা সম্ভব পরিষ্কার রাখতে চাই । সি # তে এমন কোনও পদ্ধতি আছে যা আমার পক্ষে এটি করতে পারে?

এর মতো কিছু (সিউডো কোড):

Array NewArray = oldArray.createNewArrayFromRange(int BeginIndex , int EndIndex)

Array.Copyআমার প্রয়োজন মাপসই করা হয় না । আমার নতুন অ্যারে আইটেমগুলি ক্লোন হতে হবে। Array.copyএটি কেবল একটি সি-স্টাইল memcpyসমতুল্য, আমি যা খুঁজছি তা নয়।



7
@ কীর্তন - যে "ডুপ" বিশেষত আইনেম্যুয়াল <T> চায় - যা আলাদা এবং এর সর্বোত্তম সমাধান রয়েছে; আইএমও
মার্ক গ্রাভেল

সুতরাং, যে দুটি লাইন এটি নতুন অ্যারে ঘোষণা করতে এবং কল করতে লাগবে .কপি () "ক্লিন কোড" নয়?
এড এস

2
@ এড সোয়াংগ্রেন - শৃঙ্খলিত প্রকাশের মাঝামাঝি সময়ে আপনার এটি করার প্রয়োজন হয় না, না ;
মার্ক গ্র্যাভেল

2
: ShaggyUk এর উত্তর সম্ভবত সঠিক এক stackoverflow.com/questions/943635/...
Dykam

উত্তর:


469

আপনি এটি একটি এক্সটেনশন পদ্ধতি হিসাবে যুক্ত করতে পারেন:

public static T[] SubArray<T>(this T[] data, int index, int length)
{
    T[] result = new T[length];
    Array.Copy(data, index, result, 0, length);
    return result;
}
static void Main()
{
    int[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int[] sub = data.SubArray(3, 4); // contains {3,4,5,6}
}

ক্লোনিং আপডেট করুন (যা মূল প্রশ্নে স্পষ্ট ছিল না)। আপনি যদি সত্যিই একটি গভীর ক্লোন চান; কিছুটা এইরকম:

public static T[] SubArrayDeepClone<T>(this T[] data, int index, int length)
{
    T[] arrCopy = new T[length];
    Array.Copy(data, index, arrCopy, 0, length);
    using (MemoryStream ms = new MemoryStream())
    {
        var bf = new BinaryFormatter();
        bf.Serialize(ms, arrCopy);
        ms.Position = 0;
        return (T[])bf.Deserialize(ms);
    }
}

যদিও এটির জন্য বস্তুগুলি সিরিয়ালযোগ্য ( [Serializable]বা ISerializable) হওয়া দরকার। - তুমি সহজে যথাযথ হিসাবে অন্য কোন serializer খেলোয়াড়রা পারে XmlSerializer, DataContractSerializer, protobuf-নেট, ইত্যাদি

দ্রষ্টব্য যে গভীর ক্লোনটি সিরিয়ালাইজেশন ছাড়াই কৌশলযুক্ত; বিশেষত, ICloneableবেশিরভাগ ক্ষেত্রেই বিশ্বাস করা শক্ত।


1
(স্পষ্টতই দৈর্ঘ্যের চেয়ে শেষ সূচকটি ব্যবহার করা একটি সাধারণ পরিবর্তন; আমি "যেমনটি" পোস্ট করেছি কারণ এটি আরও "সাধারণ" ব্যবহার)
মার্ক গ্রাভেল

1
তারপরে ... শক্ত; এটি
এমনটি

1
কিছু বিকল্পের জন্য আমার উত্তর এবং কয়েকটি বাস্তবায়নের লিঙ্ক দেখুন। সাব অ্যারেটিতে এটি করা অংশটি আসলেই তুচ্ছ, আপনি যা চান তা হ'ল ক্লোনিং বিট এবং এটি একটি জটিল এবং কিছুটা উন্মুক্ত প্রশ্ন যা 'সঠিক' আচরণ কী হওয়া উচিত তা সম্পর্কে আপনার প্রত্যাশার উপর পুরোপুরি নির্ভর করে ।
ShuggyCoUk

2
এটা সুন্দর. এবং এটি উল্লেখ করা ভাল যে ICloneable বিশ্বাসযোগ্য নয়, কারণ ওহ, এটি কি সর্বদা।
মার্কাস গ্রিপ

1
সি # তে গভীর ক্লোনিং করে সমস্যাগুলি আন্ডারলাইন করার জন্য ধন্যবাদ Thanks এটি সত্যই লজ্জাজনক, কারণ গভীর অনুলিপি একটি মৌলিক কাজ
দিমিত্রি সি

316

আপনি Array.Copy(...)নতুন অ্যারে তৈরি করার পরে এটি অনুলিপি করতে ব্যবহার করতে পারেন , তবে আমি মনে করি না এমন কোনও পদ্ধতি আছে যা নতুন অ্যারে তৈরি করে এবং বিভিন্ন উপাদানের অনুলিপি করে।

.NET 3.5 ব্যবহার করে আপনি লিনকুই ব্যবহার করতে পারেন:

var newArray = array.Skip(3).Take(5).ToArray();

তবে এটি কিছুটা কম দক্ষ হবে।

আরও নির্দিষ্ট পরিস্থিতির জন্য বিকল্পগুলির জন্য একই প্রশ্নের এই উত্তরটি দেখুন ।


+1 আমি এই প্রকরণটিও পছন্দ করি। জোন, আপনি কেন এটিকে কম দক্ষ হিসাবে বিবেচনা করছেন তা বাড়িয়ে তুলতে পারেন?
ইয়ান রোকে

@ জন: প্রশ্নের সাথে মেলে, তা কি "টেক (5)" হবে না? @ আইয়ান: অ্যারে.কপি পদ্ধতির মধ্যে কোনও গণক জড়িত না এবং সম্ভবত এটি একটি সরল স্মৃতিচারণ হতে পারে ...
মার্ক গ্র্যাভেল

@ মার্ক: হ্যাঁ সত্যই। খুব বেশি প্রশ্ন স্কিমিং :)
জন স্কিটি

11
@ আইয়ান: লিনকিউ পদ্ধতির দুটি স্তর (পুনরাবৃত্তকারী) পরিচয় করিয়ে দেওয়া হয়েছে, স্পষ্টভাবে আইটেমগুলি ছাড়তে হবে, এবং চূড়ান্ত অ্যারেটি আগে থেকে কত বড় হতে চলেছে তা জানে না। দুই-মিলিয়ন-এলিমেন্ট অ্যারের দ্বিতীয়ার্ধটি নেওয়ার বিষয়টি বিবেচনা করুন: একটি সাধারণ "টার্গেট অ্যারে তৈরি করুন, অনুলিপি করুন" এপ্রোচ কেবল অন্যান্য উপাদানগুলিকে স্পর্শ না করে প্রয়োজনীয় ব্লকটি অনুলিপি করবে এবং একসাথে। লিনকিউ অ্যাপ্রোচ অ্যারে পেরিয়ে চলবে যতক্ষণ না এটি প্রারম্ভের পয়েন্টে পৌঁছায়, তারপরে মানগুলি গ্রহণ করা, বাফার তৈরি করা শুরু করুন (বাফারের আকার বাড়ানো এবং পর্যায়ক্রমে অনুলিপি করা)। অনেক কম দক্ষ।
জন স্কিটি

যদি 5টি এন্ডেডেক্সেম হয় তবে সঠিক প্রশ্নটি অ্যারে হবে k স্কিপ (3) T। নিন (5-3 + 1)। টোআররে (); অর্থাত। array.Skip (StartIndex) .Take (EndIndex-StartIndex +1) .ToArray ();
ক্লাউস 78

73

আপনি ব্যবহার বিবেচনা করেছেন ArraySegment?

http://msdn.microsoft.com/en-us/library/1hsbd92d.aspx


1
এটি সম্ভবত আপনি যা চান তা করেন তবে এটি ডিফল্ট অ্যারে সিনট্যাক্সকে সমর্থন করে না, বা এটি আইমনামেবল সমর্থন করে না, তাই এটি বিশেষত পরিষ্কার নয়।
অ্যালেক্স ব্ল্যাক

5
এটি আরও upvote প্রয়োজন। আমার নিজের এক্সপ্রেসে অ্যারেসিগমেন্টের অনুলিপিটি খুব দ্রুততর হয়েছে (সর্বোপরি আমি গতি সমালোচনামূলক
স্টাফগুলির

5
@ অ্যালেক্সব্ল্যাক এটি নেট নেট ৪.৫ এর মতো দেখায় , এটি প্রয়োগ করে IEnumerable<T>এবং বিভিন্ন উপকারী ইন্টারফেসের বিভিন্ন ধরণের।
PSWg

1
ArraySegmentআসল প্রশ্নের উত্তর দিতে আপনি কীভাবে ব্যবহার করবেন?
ক্রেগ ম্যাককুইন

2
@ ক্রেইগম্যাকিউইন - নিম্নলিখিত একক-লাইন পদ্ধতির চেষ্টা করুন:IList<T> newArray = (IList<T>)new ArraySegment<T>(oldArray, beginIndex, endIndex);
skia.heliou

36

আমি দেখতে পাচ্ছি আপনি ক্লোনিং করতে চান, কেবল উল্লেখগুলি অনুলিপি করছেন না। এই ক্ষেত্রে আপনি .Selectঅ্যারে সদস্যদের তাদের ক্লোনগুলিতে প্রজেক্ট করতে ব্যবহার করতে পারেন । উদাহরণস্বরূপ, যদি আপনার উপাদানগুলি প্রয়োগ করে IClonableআপনি এরকম কিছু করতে পারেন:

var newArray = array.Skip(3).Take(5).Select(eachElement => eachElement.Clone()).ToArray();

দ্রষ্টব্য: এই সমাধানটির জন্য .NET ফ্রেমওয়ার্ক 3.5 প্রয়োজন।


এটি আরও মার্জিত।
স্মিভিকিপিডিয়া

আমি ঠিক এটিই খুঁজছিলাম। এটি যে কোনওর জন্য কাজ করে IEnumerable। আমি একজন পেতে পারেন IEnumerable, IList, IArray, ইত্যাদি, ন্যূনতম হইচই সঙ্গে ... ইনলাইন যদি আমি করতে হবে। যদি আমার গভীর অনুলিপিটির প্রয়োজন না হয় তবে আমি কেবল এটি সরিয়ে ফেলি Select। ড্রপিং Skipবা Takeআমাকে ব্যাপ্তিটি নিয়ন্ত্রণ করতে দেয়। বিকল্পভাবে, আমি এটি SkipWhileএবং / অথবা এর সাথে মিশ্রিত করতে পারি TakeWhile
মাইক

33

নিম্নলিখিত কোডটি এটি একটি লাইনে করে:

// Source array
string[] Source = new string[] { "A", "B", "C", "D" };
// Extracting a slice into another array
string[] Slice = new List<string>(Source).GetRange(2, 2).ToArray();

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

তবুও এটি উত্সটিকে ক্লোন করে না ... তবে এটি যাইহোক একটি ভাল পদ্ধতির
আইজি প্যাসকুল

1
এটি উত্সটি ক্লোন করা উচিত কারণ ToArray: (1) একটি নতুন অ্যারে তৈরি করে এবং (2) অ্যারে.কপি চালায়। শেষ পর্যন্ত উত্স এবং স্লাইস দুটি পৃথক বস্তু। পদ্ধতির সঠিক, কিন্তু, আমি Array.Copy পছন্দ করা: referencesource.microsoft.com/#mscorlib/system/collections/...
Krauss

13

সি # 8 এ তারা একটি নতুন Rangeএবং Indexটাইপ প্রবর্তন করেছে

int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Index i1 = 3;  // number 3 from beginning
Index i2 = ^4; // number 4 from end
var slice = a[i1..i2]; // { 3, 4, 5 }

12
string[] arr = { "Parrot" , "Snake" ,"Rabbit" , "Dog" , "cat" };

arr = arr.ToList().GetRange(0, arr.Length -1).ToArray();

8

মার্কের উত্তরে বিল্ডিং করা তবে কাঙ্ক্ষিত ক্লোনিং আচরণ যুক্ত করা

public static T[] CloneSubArray<T>(this T[] data, int index, int length)
    where T : ICloneable
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Clone();            
    return result;
}

এবং যদি আইক্লোনয়েবল বাস্তবায়ন খুব বেশি পরিশ্রমের মতো হয় তবে হ্যাভার্ড স্ট্র্যান্ডেনের কপিযোগ্য লাইব্রেরি ব্যবহার করে ভারী উত্তোলন করা প্রয়োজন।

using OX.Copyable;

public static T[] DeepCopySubArray<T>(
    this T[] data, int index, int length)
{
    T[] result = new T[length];
    for (int i = 0; i < length; i++)
    { 
        var original = data[index + i];
        if (original != null)
            result[i] = (T)original.Copy();            
    return result;
}

মনে রাখবেন যে ওএক্স.কপিযোগ্য বাস্তবায়ন যে কোনও একটির সাথে কাজ করে:

স্বয়ংক্রিয় অনুলিপিটি কাজ করার জন্য, তবে নীচের বিবৃতিগুলির একটি অবশ্যই ধরতে হবে:

  • এর ধরণের অবশ্যই প্যারামিটারলেস কনস্ট্রাক্টর থাকতে হবে, বা
  • এটি অবশ্যই একটি অনুলিপিযোগ্য, বা
  • এটির জন্য এটির জন্য একটি IInstancePovider নিবন্ধিত থাকতে হবে।

সুতরাং এটি আপনার প্রায় কোনও পরিস্থিতিতে আবরণ করা উচিত। আপনি যদি সাবজেক্টে ক্লোনিং করছেন যেখানে সাব গ্রাফের মতো ডিবি সংযোগ বা ফাইল / স্ট্রিম হ্যান্ডলগুলির মতো জিনিস রয়েছে আপনার স্পষ্টতই সমস্যা রয়েছে তবে এটি কোনও সাধারণীকৃত গভীর কপির জন্য সত্য true

পরিবর্তে আপনি যদি আরও কিছু গভীর অনুলিপি ব্যবহার করতে চান তবে এই নিবন্ধটি আরও কয়েকটিকে তালিকাভুক্ত করে যাতে আমি আপনার নিজের লেখার চেষ্টা না করার পরামর্শ দিই।


প্রথমটি সম্ভবত কাঙ্ক্ষিত সমাধান, কারণ তিনি ক্লোনিংয়ের জন্য জিজ্ঞাসা করছেন। নোট করুন যে অনুলিপি পদ্ধতিটি সহ, আপনাকে সম্ভবত শূন্যতার জন্যও পরীক্ষা করতে হবে না, কারণ এটি কোনও এক্সটেনশন পদ্ধতি, যদি পদ্ধতি নিজেই ইতিমধ্যে এটি কাজ করে। ব্যবহার করে দেখুন মূল্য.
ডাইকম

হ্যাঁ আমি নাল চেকটি নোট করেছি তবে তিনি যদি উত্সটি না পড়েন তবে ওপিকে বিভ্রান্ত করতে চান না।
ShuggyCoUk

2
কেবলমাত্র একটি পৃথক নোট: গিটহাবের অনুলিপি করার সর্বশেষতম সংস্করণে প্যারামিটারলেস কনস্ট্রাক্টর থাকা সামগ্রীর প্রয়োজন নেই। :) github.com/havard/copyable
হাভার্ড এস

8

আপনি এটি মোটামুটি সহজভাবে করতে পারেন;

    object[] foo = new object[10];
    object[] bar = new object[7];   
    Array.Copy(foo, 3, bar, 0, 7);  

না, বারটি এখনও শূন্য থাকবে। অ্যারে.কপি যাদুতে নতুন অ্যারে তৈরি করে না, বিশেষত যেহেতু বারটি রেফ বা আউট দিয়ে পাস করা হয় না।
Zr40

2
ওহ হ্যাঁ, আপনার অধিকার, আমি তাড়াহুড়ো করে তাড়াহুড়ো করেছিলাম, কিন্তু ওহে, আপনার লেখার সমালোচনা যখন সংশোধন করা উচিত তখনই গঠনমূলক সমালোচনা প্রত্যেকের পক্ষে অনেক বেশি উপকারী। সুতরাং সেই অ্যারে.কপির আগে আপনি একটি "বার = নতুন অবজেক্ট [7]" করেন;
এলোমেলোভাবে নাম 42

4

আমি মনে করি আপনি যে কোডটি সন্ধান করছেন তা হ'ল:

Array.Copy(oldArray, 0, newArray, BeginIndex, EndIndex - BeginIndex)


আমি মনে করি আমি এখানে কিছু ভাল বন্ধুর তৈরি করছি .... আপনার মত একই উত্তর;) এবং আমি প্রচুর ভোট পেয়েছি !! Hah !! যাইহোক, ভাল সময় ভাল সময়।
এলোমেলোভাবে নাম 42

3

ডেটা অনুলিপি করার বিকল্প হিসাবে আপনি একটি মোড়ক তৈরি করতে পারেন যা আপনাকে মূল অ্যারের কোনও অংশে অ্যাক্সেস দেয় যাতে এটি অ্যারের অংশের অনুলিপি হয়। সুবিধাটি হ'ল আপনি মেমরিতে ডেটাটির অন্য অনুলিপিটি পান না এবং ডেটা অ্যাক্সেস করার সময় ত্রুটিটি সামান্য ওভারহেড হয়।

public class SubArray<T> : IEnumerable<T> {

   private T[] _original;
   private int _start;

   public SubArray(T[] original, int start, int len) {
      _original = original;
      _start = start;
      Length = len;
   }

   public T this[int index] {
      get {
         if (index < 0 || index >= Length) throw new IndexOutOfRangeException();
         return _original[_start + index];
      }
   }

   public int Length { get; private set; }

   public IEnumerator<T> GetEnumerator() {
      for (int i = 0; i < Length; i++) {
        yield return _original[_start + i];
      }
   }

   IEnumerator IEnumerable.GetEnumerator() {
      return GetEnumerator();
   }

}

ব্যবহার:

int[] original = { 1, 2, 3, 4, 5 };
SubArray<int> copy = new SubArray<int>(original, 2, 2);

Console.WriteLine(copy.Length); // shows: 2
Console.WriteLine(copy[0]); // shows: 3
foreach (int i in copy) Console.WriteLine(i); // shows 3 and 4

@ রবার্ট: না, তা নয়। পরিবর্তে একটি অ্যারে বিভাগ ব্যবহার করার চেষ্টা করুন এবং আপনি সূচী দ্বারা আইটেমগুলি অ্যাক্সেস করতে পারবেন না, আপনি আইটেমগুলির মাধ্যমে পুনরাবৃত্তি করতে পারবেন না see
গুফা 15

2

অ্যারে.কন্সট্রেইনডকপি কাজ করবে।

public static void ConstrainedCopy (
    Array sourceArray,
    int sourceIndex,
    Array destinationArray,
    int destinationIndex,
    int length
)

2
এটি কেবল তথ্য অনুলিপি করে; এটি নতুন অ্যারে ইত্যাদি তৈরি করবে না; এবং অ্যারেটি যদি নতুন হয় তবে আমরা অ্যারে.কপি ব্যবহার করতে পারি যা আরও দক্ষ (অতিরিক্ত চেক / রোলব্যাকের প্রয়োজন নেই)।
মার্ক গ্র্যাভেল

ঠিক আছে, তবে একটি নতুন অ্যারে তৈরি করা কোডের একমাত্র লাইন এবং কোনও নতুন পদ্ধতির প্রয়োজন নেই। আমি সম্মত হই যে অ্যারে.কপি পাশাপাশি কাজ করবে।
ক্রাশকার

1

এমন কোনও একক পদ্ধতি নেই যা আপনি যা চান তা করবে। আপনার অ্যারেতে ক্লাসের জন্য আপনার ক্লোন পদ্ধতি উপলব্ধ করতে হবে। তারপরে, যদি লিনকুই একটি বিকল্প হয়:

Foo[] newArray = oldArray.Skip(3).Take(5).Select(item => item.Clone()).ToArray();

class Foo
{
    public Foo Clone()
    {
        return (Foo)MemberwiseClone();
    }
}

1

কিভাবে useing সম্পর্কে Array.ConstrainedCopy :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
Array.ConstrainedCopy(ArrayOne, 3, ArrayTwo, 0, 7-3);

নীচে আমার মূল পোস্টটি দেওয়া আছে। এটি কাজ করবে না

আপনি অ্যারে ব্যবহার করতে পারেন। কপিটো :

int[] ArrayOne = new int[8] {1,2,3,4,5,6,7,8};
int[] ArrayTwo = new int[5];
ArrayOne.CopyTo(ArrayTwo,3); //starts copy at index=3 until it reaches end of
                             //either array

1

এটি সম্পর্কে:

public T[] CloneCopy(T[] array, int startIndex, int endIndex) where T : ICloneable
{
    T[] retArray = new T[endIndex - startIndex];
    for (int i = startIndex; i < endIndex; i++)
    {
        array[i - startIndex] = array[i].Clone();
    }
    return retArray;

}

তারপরে আপনার এই ক্লাসটি ব্যবহার করা দরকার এমন সমস্ত ক্লাসে আপনার আইসিএলনেবল ইন্টারফেস প্রয়োগ করতে হবে তবে এটি করা উচিত।


1

এটি সত্য কত গভীর তা আমি নিশ্চিত নই, তবে:

MyArray.ToList<TSource>().GetRange(beginningIndex, endIndex).ToArray()

এটি কিছুটা ওভারহেড, তবে এটি একটি অপ্রয়োজনীয় পদ্ধতি কেটে যেতে পারে।


1

সি # 8 সূচনা থেকে শেষ সূচি পর্যন্ত সাবারিটি পেতে রেঞ্জ নামে পরিচিত বৈশিষ্ট্য সরবরাহ করেছে। আপনি এটি এটি ব্যবহার করতে পারেন।

Index i1 = 3; // number 3 from beginning  
Index i2 = ^4; // number 4 from end  
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };  
var slice = a[i1..i2]; // { 3, 4, 5 }

0

ক্লোনিং যতদূর যায়, সিরিয়ালাইজেশন আপনার নির্মাণকারীদের কল করে না বলে আমি মনে করি। এটি শ্রেণীর আক্রমণকারীদের বিরতি দিতে পারে যদি আপনি কর্টারের মধ্যে আকর্ষণীয় কাজ করে থাকেন।

দেখে মনে হচ্ছে সুরক্ষিত বাজি হ'ল ভার্চুয়াল ক্লোন পদ্ধতিগুলি কপি কন্সট্রাক্টরদের কল করছে।

protected MyDerivedClass(MyDerivedClass myClass) 
{
  ...
}

public override MyBaseClass Clone()
{
  return new MyDerivedClass(this);
}

সিরিয়ালাইজেশন আপনার নির্মাণকারীদের কল করে কিনা তা নির্দিষ্ট সিরিয়ালাইজারের উপর নির্ভর করে। কিছু করেন, কেউ করেন না। তবে যা সাধারণত কলব্যাক সহায়তা দেয় না তাদের আপনাকে প্রয়োজনীয় কোনও ফিক্সআপগুলি করার অনুমতি দেয়।
মার্ক গ্রাভেল

এটি সিরিয়ালাইজেশনের আরও ঘর্ষণ পয়েন্ট হাইলাইট করে: আপনাকে ডিফল্ট কনস্ট্রাক্টর সরবরাহ করতে হবে।
হান্স মালহেরবে

0

অ্যারেতে ক্লোনিং উপাদান এমন কিছু নয় যা সর্বজনীন উপায়ে করা যায়। আপনি কি ডিপ ক্লোনিং বা সমস্ত সদস্যের একটি সাধারণ অনুলিপি চান?

আসুন "সেরা প্রচেষ্টা" পদ্ধতির জন্য যান: আইসিএলনেবল ইন্টারফেস বা বাইনারি সিরিয়ালাইজেশন ব্যবহার করে ক্লোনিং অবজেক্টগুলি:

public static class ArrayExtensions
{
  public static T[] SubArray<T>(this T[] array, int index, int length)
  {
    T[] result = new T[length];

    for (int i=index;i<length+index && i<array.Length;i++)
    {
       if (array[i] is ICloneable)
          result[i-index] = (T) ((ICloneable)array[i]).Clone();
       else
          result[i-index] = (T) CloneObject(array[i]);
    }

    return result;
  }

  private static object CloneObject(object obj)
  {
    BinaryFormatter formatter = new BinaryFormatter();

    using (MemoryStream stream = new MemoryStream())
    {
      formatter.Serialize(stream, obj);

      stream.Seek(0,SeekOrigin.Begin);

      return formatter.Deserialize(stream);
    }
  }
}

এটি একটি নিখুঁত সমাধান নয়, কারণ এমন কোনও কিছুই নেই যা কোনও ধরণের অবজেক্টের জন্য কাজ করবে।


কি ফলাফলের মতো কিছু হবে না [i-index] = (টি) ...?
ডোনাল্ড বাইার্ড

হ্যাঁ :) এবং কেবল এটিই নয়। লুপের সীমানাটি ভুল। আমি এটা ঠিক করব. ধন্যবাদ!
ফিলিপ লেবার্ট

0

আপনি মাইক্রোসফ্ট দ্বারা তৈরি ক্লাস নিতে পারেন:

internal class Set<TElement>
{
    private int[] _buckets;
    private Slot[] _slots;
    private int _count;
    private int _freeList;
    private readonly IEqualityComparer<TElement> _comparer;

    public Set()
        : this(null)
    {
    }

    public Set(IEqualityComparer<TElement> comparer)
    {
        if (comparer == null)
            comparer = EqualityComparer<TElement>.Default;
        _comparer = comparer;
        _buckets = new int[7];
        _slots = new Slot[7];
        _freeList = -1;
    }

    public bool Add(TElement value)
    {
        return !Find(value, true);
    }

    public bool Contains(TElement value)
    {
        return Find(value, false);
    }

    public bool Remove(TElement value)
    {
        var hashCode = InternalGetHashCode(value);
        var index1 = hashCode % _buckets.Length;
        var index2 = -1;
        for (var index3 = _buckets[index1] - 1; index3 >= 0; index3 = _slots[index3].Next)
        {
            if (_slots[index3].HashCode == hashCode && _comparer.Equals(_slots[index3].Value, value))
            {
                if (index2 < 0)
                    _buckets[index1] = _slots[index3].Next + 1;
                else
                    _slots[index2].Next = _slots[index3].Next;
                _slots[index3].HashCode = -1;
                _slots[index3].Value = default(TElement);
                _slots[index3].Next = _freeList;
                _freeList = index3;
                return true;
            }
            index2 = index3;
        }
        return false;
    }

    private bool Find(TElement value, bool add)
    {
        var hashCode = InternalGetHashCode(value);
        for (var index = _buckets[hashCode % _buckets.Length] - 1; index >= 0; index = _slots[index].Next)
        {
            if (_slots[index].HashCode == hashCode && _comparer.Equals(_slots[index].Value, value))
                return true;
        }
        if (add)
        {
            int index1;
            if (_freeList >= 0)
            {
                index1 = _freeList;
                _freeList = _slots[index1].Next;
            }
            else
            {
                if (_count == _slots.Length)
                    Resize();
                index1 = _count;
                ++_count;
            }
            int index2 = hashCode % _buckets.Length;
            _slots[index1].HashCode = hashCode;
            _slots[index1].Value = value;
            _slots[index1].Next = _buckets[index2] - 1;
            _buckets[index2] = index1 + 1;
        }
        return false;
    }

    private void Resize()
    {
        var length = checked(_count * 2 + 1);
        var numArray = new int[length];
        var slotArray = new Slot[length];
        Array.Copy(_slots, 0, slotArray, 0, _count);
        for (var index1 = 0; index1 < _count; ++index1)
        {
            int index2 = slotArray[index1].HashCode % length;
            slotArray[index1].Next = numArray[index2] - 1;
            numArray[index2] = index1 + 1;
        }
        _buckets = numArray;
        _slots = slotArray;
    }

    internal int InternalGetHashCode(TElement value)
    {
        if (value != null)
            return _comparer.GetHashCode(value) & int.MaxValue;
        return 0;
    }

    internal struct Slot
    {
        internal int HashCode;
        internal TElement Value;
        internal int Next;
    }
}

এবং তারপর

public static T[] GetSub<T>(this T[] first, T[] second)
    {
        var items = IntersectIteratorWithIndex(first, second);
        if (!items.Any()) return new T[] { };


        var index = items.First().Item2;
        var length = first.Count() - index;
        var subArray = new T[length];
        Array.Copy(first, index, subArray, 0, length);
        return subArray;
    }

    private static IEnumerable<Tuple<T, Int32>> IntersectIteratorWithIndex<T>(IEnumerable<T> first, IEnumerable<T> second)
    {
        var firstList = first.ToList();
        var set = new Set<T>();
        foreach (var i in second)
            set.Add(i);
        foreach (var i in firstList)
        {
            if (set.Remove(i))
                yield return new Tuple<T, Int32>(i, firstList.IndexOf(i));
        }
    }

0

এটি করার জন্য এটি সর্বোত্তম উপায়, আমি খুঁজে পেয়েছি:

private void GetSubArrayThroughArraySegment() {
  int[] array = { 10, 20, 30 };
  ArraySegment<int> segment = new ArraySegment<int>(array,  1, 2);
  Console.WriteLine("-- Array --");
  int[] original = segment.Array;
  foreach (int value in original)
  {
    Console.WriteLine(value);
  }
  Console.WriteLine("-- Offset --");
  Console.WriteLine(segment.Offset);
  Console.WriteLine("-- Count --");
  Console.WriteLine(segment.Count);

  Console.WriteLine("-- Range --");
  for (int i = segment.Offset; i <= segment.Count; i++)
  {
    Console.WriteLine(segment.Array[i]);
  }
}

আশা করি এটা সাহায্য করবে!


0

অব্যাহতি পদ্ধতি ব্যবহার করুন:

public static T[] Slice<T>(this T[] source, int start, int end)
    {
        // Handles negative ends.
        if (end < 0)
        {
            end = source.Length + end;
        }
        int len = end - start;

        // Return new array.
        T[] res = new T[len];
        for (int i = 0; i < len; i++)
        {
            res[i] = source[i + start];
        }
        return res;
    }

এবং আপনি এটি ব্যবহার করতে পারেন

var NewArray = OldArray.Slice(3,7);

0

সিস্টেম থেকে কোড.প্রাইভেট.কোরলিব.ডিল:

public static T[] GetSubArray<T>(T[] array, Range range)
{
    if (array == null)
    {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
    }
    (int Offset, int Length) offsetAndLength = range.GetOffsetAndLength(array.Length);
    int item = offsetAndLength.Offset;
    int item2 = offsetAndLength.Length;
    if (default(T) != null || typeof(T[]) == array.GetType())
    {
        if (item2 == 0)
        {
            return Array.Empty<T>();
        }
        T[] array2 = new T[item2];
        Buffer.Memmove(ref Unsafe.As<byte, T>(ref array2.GetRawSzArrayData()), ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), item), (uint)item2);
        return array2;
    }
    T[] array3 = (T[])Array.CreateInstance(array.GetType().GetElementType(), item2);
    Array.Copy(array, item, array3, 0, item2);
    return array3;
}



0

এটি আপনার ক্লোনিংয়ের প্রয়োজনীয়তা পূরণ করে না তবে এটি করা অনেক উত্তরের চেয়ে সহজ বলে মনে হচ্ছে:

Array NewArray = new ArraySegment(oldArray,BeginIndex , int Count).ToArray();

-1
public   static   T[]   SubArray<T>(T[] data, int index, int length)
        {
            List<T> retVal = new List<T>();
            if (data == null || data.Length == 0)
                return retVal.ToArray();
            bool startRead = false;
            int count = 0;
            for (int i = 0; i < data.Length; i++)
            {
                if (i == index && !startRead)
                    startRead = true;
                if (startRead)
                {

                    retVal.Add(data[i]);
                    count++;

                    if (count == length)
                        break;
                }
            }
            return retVal.ToArray();
        }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.