আমার # সিতে 3 বাইট অ্যারে রয়েছে যা আমাকে একটিতে একত্রিত করতে হবে। এই কাজটি সম্পন্ন করার সবচেয়ে দক্ষ পদ্ধতি কী হবে?
Concat
পদ্ধতিটি ব্যবহার করতে পারেন :IEnumerable<byte> arrays = array1.Concat(array2).Concat(array3);
আমার # সিতে 3 বাইট অ্যারে রয়েছে যা আমাকে একটিতে একত্রিত করতে হবে। এই কাজটি সম্পন্ন করার সবচেয়ে দক্ষ পদ্ধতি কী হবে?
Concat
পদ্ধতিটি ব্যবহার করতে পারেন :IEnumerable<byte> arrays = array1.Concat(array2).Concat(array3);
উত্তর:
আদিম ধরণের (বাইট সহ) জন্য, System.Buffer.BlockCopy
পরিবর্তে ব্যবহার করুন System.Array.Copy
। এটি দ্রুত।
আমি প্রস্তাবিত প্রতিটি পদ্ধতির প্রত্যেককে 10 টি বাইটের 3 অ্যারে ব্যবহার করে 1 মিলিয়ন বার লুপে নির্বাহ করি। ফলাফল এখানে:
System.Array.Copy
- 0.2187556 সেকেন্ডSystem.Buffer.BlockCopy
- 0.1406286 সেকেন্ডআমি প্রতিটি অ্যারের আকার 100 টি উপাদান করে বাড়িয়ে পরীক্ষাটি আবার চালিয়েছি:
System.Array.Copy
- 0.2812554 সেকেন্ডSystem.Buffer.BlockCopy
- 0.2500048 সেকেন্ডআমি প্রতিটি অ্যারের আকার 1000 উপাদানগুলিতে বাড়িয়েছি এবং আবার পরীক্ষা চালিয়েছি:
System.Array.Copy
- 1.0781457 সেকেন্ডSystem.Buffer.BlockCopy
- 1.0156445 সেকেন্ডঅবশেষে, আমি প্রতিটি অ্যারের আকার 1 মিলিয়নে বাড়িয়েছি এবং পরীক্ষাটি আবার চালিয়েছি, প্রতিটি লুপকে কেবল 4000 বার কার্যকর করে :
System.Array.Copy
- 13.4533833 সেকেন্ডSystem.Buffer.BlockCopy
- 13.1096267 সেকেন্ডসুতরাং, আপনার যদি নতুন বাইট অ্যারে প্রয়োজন হয় তবে ব্যবহার করুন
byte[] rv = new byte[a1.Length + a2.Length + a3.Length];
System.Buffer.BlockCopy(a1, 0, rv, 0, a1.Length);
System.Buffer.BlockCopy(a2, 0, rv, a1.Length, a2.Length);
System.Buffer.BlockCopy(a3, 0, rv, a1.Length + a2.Length, a3.Length);
কিন্তু, যদি আপনি একটি ব্যবহার করতে পারেন IEnumerable<byte>
, স্পষ্টভাবে LINQ এর CONCAT <> পদ্ধতি পছন্দ করে। এটি সি # ফলন অপারেটরের চেয়ে সামান্য ধীর, তবে আরও সংক্ষিপ্ত এবং আরও মার্জিত।
IEnumerable<byte> rv = a1.Concat(a2).Concat(a3);
আপনার যদি স্বেচ্ছাসেবী সংখ্যক অ্যারে থাকে এবং .NET 3.5 ব্যবহার করা হয় তবে আপনি System.Buffer.BlockCopy
সমাধানটিকে আরও সাধারণভাবে তৈরি করতে পারেন :
private byte[] Combine(params byte[][] arrays)
{
byte[] rv = new byte[arrays.Sum(a => a.Length)];
int offset = 0;
foreach (byte[] array in arrays) {
System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);
offset += array.Length;
}
return rv;
}
* দ্রষ্টব্য: উপরের ব্লকটির কাজ করার জন্য আপনাকে নীচের অংশে নীচের নেমস্পেস যুক্ত করতে হবে।
using System.Linq;
পরবর্তী ডেটা স্ট্রাকচারের পুনরাবৃত্তির বিষয়ে জন স্কিটির বক্তব্যটি (বাইট অ্যারে বনাম আইয়ুনিউরেবল <বিট>), আমি শেষ টাইমিং টেস্টটি পুনরায় চালিয়েছি (1 মিলিয়ন উপাদান, 4000 পুনরাবৃত্তি) প্রতিটিটির সাথে পুরো অ্যারের উপরে পুনরাবৃত্তি করে এমন একটি লুপ যুক্ত করেছি পাস:
System.Array.Copy
- 78.20550510 সেকেন্ডSystem.Buffer.BlockCopy
- 77.89261900 সেকেন্ডমুল বক্তব্যটি হ'ল, উভয় তৈরি এবং ফলস্বরূপ ডেটা স্ট্রাকচারের দক্ষতা বোঝা খুব গুরুত্বপূর্ণ । কেবল সৃষ্টির দক্ষতার উপর ফোকাস করা ব্যবহারের সাথে সম্পর্কিত অদক্ষতা উপেক্ষা করতে পারে। কুডোস, জোন
অনেক উত্তর আমার কাছে বর্ণিত প্রয়োজনীয়তা উপেক্ষা করছে বলে মনে হচ্ছে:
এই দু'জনে মিলে একটি লাইনকিউ সিকোয়েন্সকে বাইটস থেকে বের করে দেয় - এর সাথে yield
যে কোনও কিছুই পুরো ক্রমটি না ঘটিয়ে চূড়ান্ত আকারটি অর্জন করা অসম্ভব করে দেয়।
সেই না হন, তাহলে বাস্তব কোর্সের প্রয়োজনীয়তা LINQ একটি পুরোপুরি ভালো সমাধান (অথবা হতে পারে IList<T>
বাস্তবায়ন)। তবে, আমি ধরে নেব যে সুপারডামবেল জানেন তিনি কী চান।
(সম্পাদনা: আমার আরও একটি ধারণা ছিল। অ্যারের অনুলিপি তৈরি করা এবং অলসভাবে সেগুলি পড়ার মধ্যে একটি বড় শব্দার্থক পার্থক্য রয়েছে calling কল করার পরে আপনি যদি কোনও "উত্স" অ্যারে ডেটা পরিবর্তন করেন তবে কী ঘটবে তা বিবেচনা করুন Combine
ঘটছে।। (অথবা যাই হোক না কেন ) পদ্ধতি তবে ফলাফলটি ব্যবহারের আগে - অলস মূল্যায়নের সাথে, সেই পরিবর্তনটি দৃশ্যমান হবে an তাত্ক্ষণিক অনুলিপি সহ, এটি হবে না Dif বিভিন্ন পরিস্থিতিতে বিভিন্ন আচরণের জন্য আহ্বান জানানো হবে - সচেতন হওয়ার জন্য কেবল কিছু))
এখানে আমার প্রস্তাবিত পদ্ধতিগুলি রয়েছে - যা অন্যান্য উত্তরগুলির সাথে সামঞ্জস্যপূর্ণ, অবশ্যই :)
public static byte[] Combine(byte[] first, byte[] second)
{
byte[] ret = new byte[first.Length + second.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
return ret;
}
public static byte[] Combine(byte[] first, byte[] second, byte[] third)
{
byte[] ret = new byte[first.Length + second.Length + third.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
Buffer.BlockCopy(third, 0, ret, first.Length + second.Length,
third.Length);
return ret;
}
public static byte[] Combine(params byte[][] arrays)
{
byte[] ret = new byte[arrays.Sum(x => x.Length)];
int offset = 0;
foreach (byte[] data in arrays)
{
Buffer.BlockCopy(data, 0, ret, offset, data.Length);
offset += data.Length;
}
return ret;
}
অবশ্যই "প্যারামগুলি" সংস্করণটির জন্য প্রথমে বাইট অ্যারেগুলির একটি অ্যারে তৈরি করা দরকার যা অতিরিক্ত অদক্ষতার পরিচয় দেয়।
কোড পরিষ্কারের জন্য আমি ম্যাটসের লিনকিউ উদাহরণটি আরও একধাপ এগিয়ে নিয়েছি:
byte[] rv = a1.Concat(a2).Concat(a3).ToArray();
আমার ক্ষেত্রে, অ্যারেগুলি ছোট, তাই আমি পারফরম্যান্স সম্পর্কে উদ্বিগ্ন নই।
আপনার যদি কেবল নতুন বাইট অ্যারে প্রয়োজন হয় তবে নিম্নলিখিতগুলি ব্যবহার করুন:
byte[] Combine(byte[] a1, byte[] a2, byte[] a3)
{
byte[] ret = new byte[a1.Length + a2.Length + a3.Length];
Array.Copy(a1, 0, ret, 0, a1.Length);
Array.Copy(a2, 0, ret, a1.Length, a2.Length);
Array.Copy(a3, 0, ret, a1.Length + a2.Length, a3.Length);
return ret;
}
বিকল্পভাবে, আপনার যদি কেবল একটিমাত্র আইনিংরেবলের প্রয়োজন হয়, তবে সি # 2.0 ফলন অপারেটরটি ব্যবহার করে বিবেচনা করুন:
IEnumerable<byte> Combine(byte[] a1, byte[] a2, byte[] a3)
{
foreach (byte b in a1)
yield return b;
foreach (byte b in a2)
yield return b;
foreach (byte b in a3)
yield return b;
}
আমি আসলে কনক্যাট ব্যবহার করে কিছু সমস্যা নিয়ে এসেছি ... (১০-কোটির মধ্যে অ্যারে দিয়ে, এটি আসলে ক্র্যাশ হয়েছিল)।
আমি নিম্নলিখিতগুলি সহজ, সহজ বলে মনে করেছি এবং আমার উপর ক্রাশ না করে যথেষ্ট কাজ করে এবং এটি যে কোনও সংখ্যক অ্যারে (কেবল তিন নয়) এর জন্য কাজ করে (এটি লিনকিউ ব্যবহার করে):
public static byte[] ConcatByteArrays(params byte[][] arrays)
{
return arrays.SelectMany(x => x).ToArray();
}
স্মৃতিধারার ক্লাসটি আমার জন্য খুব সুন্দরভাবে এই কাজটি করে। আমি বাফার ক্লাসটি স্মৃতিধারার চেয়ে দ্রুত চালাতে পারিনি।
using (MemoryStream ms = new MemoryStream())
{
ms.Write(BitConverter.GetBytes(22),0,4);
ms.Write(BitConverter.GetBytes(44),0,4);
ms.ToArray();
}
public static bool MyConcat<T>(ref T[] base_arr, ref T[] add_arr)
{
try
{
int base_size = base_arr.Length;
int size_T = System.Runtime.InteropServices.Marshal.SizeOf(base_arr[0]);
Array.Resize(ref base_arr, base_size + add_arr.Length);
Buffer.BlockCopy(add_arr, 0, base_arr, base_size * size_T, add_arr.Length * size_T);
}
catch (IndexOutOfRangeException ioor)
{
MessageBox.Show(ioor.Message);
return false;
}
return true;
}
where T : struct
) সীমাবদ্ধ করার চেষ্টা করতে পারেন , তবে - সিএলআরের অভ্যন্তরের বিশেষজ্ঞ না হয়ে - আপনি নির্দিষ্ট স্ট্রাকগুলিতেও ব্যতিক্রম পেতে পারেন কিনা তা আমি বলতে পারিনি I (উদাহরণস্বরূপ যদি সেগুলিতে রেফারেন্স প্রকারের ক্ষেত্রগুলি থাকে)
public static byte[] Concat(params byte[][] arrays) {
using (var mem = new MemoryStream(arrays.Sum(a => a.Length))) {
foreach (var array in arrays) {
mem.Write(array, 0, array.Length);
}
return mem.ToArray();
}
}
অ্যারে একত্রিত করতে জেনেরিকগুলি ব্যবহার করতে পারেন। নিম্নলিখিত কোডটি সহজেই তিনটি অ্যারে প্রসারিত করা যায়। এই ধরণের অ্যারেগুলির জন্য আপনাকে কখনই কোড নকল করার প্রয়োজন হবে না। উপরের কিছু উত্তর আমার কাছে অতিরিক্ত জটিল বলে মনে হচ্ছে।
private static T[] CombineTwoArrays<T>(T[] a1, T[] a2)
{
T[] arrayCombined = new T[a1.Length + a2.Length];
Array.Copy(a1, 0, arrayCombined, 0, a1.Length);
Array.Copy(a2, 0, arrayCombined, a1.Length, a2.Length);
return arrayCombined;
}
এখানে @ জোন স্কিটের দেওয়া উত্তরের একটি সাধারণীকরণ দেওয়া আছে। এটি মূলত একই, কেবল এটি কোনও ধরণের অ্যারের জন্যই ব্যবহারযোগ্য, কেবল বাইটগুলি নয়:
public static T[] Combine<T>(T[] first, T[] second)
{
T[] ret = new T[first.Length + second.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
return ret;
}
public static T[] Combine<T>(T[] first, T[] second, T[] third)
{
T[] ret = new T[first.Length + second.Length + third.Length];
Buffer.BlockCopy(first, 0, ret, 0, first.Length);
Buffer.BlockCopy(second, 0, ret, first.Length, second.Length);
Buffer.BlockCopy(third, 0, ret, first.Length + second.Length,
third.Length);
return ret;
}
public static T[] Combine<T>(params T[][] arrays)
{
T[] ret = new T[arrays.Sum(x => x.Length)];
int offset = 0;
foreach (T[] data in arrays)
{
Buffer.BlockCopy(data, 0, ret, offset, data.Length);
offset += data.Length;
}
return ret;
}
sizeof(...)
এবং আপনার অনুলিপি করতে চান এমন উপাদানগুলির সংখ্যা দ্বারা গুণিত করতে চান, তবে আকারটি জেনেরিক টাইপের সাথে ব্যবহার করা যায় না। কিছু ধরণের জন্য - এটি ব্যবহার করা সম্ভব Marshal.SizeOf(typeof(T))
, তবে আপনি নির্দিষ্ট ধরণের (যেমন স্ট্রিং) দিয়ে রানটাইম ত্রুটি পাবেন। সিএলআর প্রকারের অভ্যন্তরীণ কাজের আরও বিশদ জ্ঞান সহকারে কেউ এখানে সম্ভাব্য সমস্ত ফাঁদ চিহ্নিত করতে সক্ষম হবেন। বলার অপেক্ষা রাখে না যে জেনেরিক অ্যারে কনটেনটেশন পদ্ধতি [ব্লককপি ব্যবহার করে] লেখা তুচ্ছ নয়।
/// <summary>
/// Combine two Arrays with offset and count
/// </summary>
/// <param name="src1"></param>
/// <param name="offset1"></param>
/// <param name="count1"></param>
/// <param name="src2"></param>
/// <param name="offset2"></param>
/// <param name="count2"></param>
/// <returns></returns>
public static T[] Combine<T>(this T[] src1, int offset1, int count1, T[] src2, int offset2, int count2)
=> Enumerable.Range(0, count1 + count2).Select(a => (a < count1) ? src1[offset1 + a] : src2[offset2 + a - count1]).ToArray();
আপনাকে কেবলমাত্র বাইট অ্যারেগুলির তালিকা পাস করতে হবে এবং এই ফাংশনটি আপনাকে বাইটের অ্যারে (মার্জড) ফিরিয়ে দেবে। এটি আমার মনে হয় সবচেয়ে ভাল সমাধান :)।
public static byte[] CombineMultipleByteArrays(List<byte[]> lstByteArray)
{
using (var ms = new MemoryStream())
{
using (var doc = new iTextSharp.text.Document())
{
using (var copy = new PdfSmartCopy(doc, ms))
{
doc.Open();
foreach (var p in lstByteArray)
{
using (var reader = new PdfReader(p))
{
copy.AddDocument(reader);
}
}
doc.Close();
}
}
return ms.ToArray();
}
}
কনক্যাট হ'ল সঠিক উত্তর, তবে কোনও কারণে একটি নিয়ন্ত্রিত জিনিস সর্বাধিক ভোট পাচ্ছে। আপনি যদি উত্তরটি পছন্দ করেন তবে সম্ভবত আপনি আরও সাধারণ সমাধানটি আরও বেশি পছন্দ করতে পারেন:
IEnumerable<byte> Combine(params byte[][] arrays)
{
foreach (byte[] a in arrays)
foreach (byte b in a)
yield return b;
}
যা আপনাকে এই জাতীয় জিনিসগুলি করতে দেয়:
byte[] c = Combine(new byte[] { 0, 1, 2 }, new byte[] { 3, 4, 5 }).ToArray();