কীভাবে সিঙ্গল অ্যারে একক মান দিয়ে পপুলেট / ইনস্ট্যান্ট করবেন?


205

আমি জানি যে সি # তে মান ধরণের তাত্ক্ষণিক অ্যারেগুলি স্বয়ংক্রিয়ভাবে টাইপের ডিফল্ট মান (যেমন বুলের জন্য মিথ্যা, 0 প্রকার ইত্যাদির জন্য ইত্যাদি) জনবসতিপূর্ণ ।

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

 // Example pseudo-code:
 bool[] abValues = new[1000000];
 Array.Populate(abValues, true);

 // Currently how I'm handling this:
 bool[] abValues = new[1000000];
 for (int i = 0; i < 1000000; i++)
 {
     abValues[i] = true;
 }

অ্যারের মাধ্যমে পুনরাবৃত্তি হওয়া এবং প্রতিটি মানকে সত্যে পুনরায় সেট করা অকার্যকর বলে মনে হয়। এদিক ওদিক কি আছে? সব মান ফ্লিপ করে?

এই প্রশ্নটি টাইপ করার পরে এবং এটি সম্পর্কে চিন্তা করার পরে, আমি অনুমান করছি যে ডিফল্ট মানগুলি কেবল সি # এই বিষয়গুলির মেমরির বরাদ্দকে কীভাবে পর্দার আড়ালে পরিচালনা করে তার ফলস্বরূপ, তাই আমি ধারণা করি এটি করা সম্ভব নয়। তবে আমি এখনও নিশ্চিতভাবে জানতে চাই!


আমি সাধারণত নাম_ই_ফাউন্ড থেকে ইস_স্টিল_হাইডিং এ পরিবর্তন করি। যদিও উত্তরগুলি পছন্দ করুন, আমার কোনও পরীক্ষার ক্ষেত্রে অ্যারের জন্য একই কাজ করা দরকার। (ভাল প্রশ্ন)
ctrl-alt-delor

উত্তর:


146

ফ্রেমওয়ার্ক পদ্ধতিটি জানেন না তবে আপনি এটির জন্য একটি দ্রুত সহায়ক লিখতে পারেন।

public static void Populate<T>(this T[] arr, T value ) {
  for ( int i = 0; i < arr.Length;i++ ) {
    arr[i] = value;
  }
}

3
আপনার যদি অনুলিপিটির প্রয়োজন না হয় তবে i++ এর পরিবর্তে ++ i পছন্দ করুন।
void.pointer

24
i ++ অনুলিপি i, ইনক্রিমেন্ট i এবং মূল মানটি দেয়। ++ আমি কেবল বর্ধিত মানটি ফিরিয়ে দিই। সুতরাং ++ আমি দ্রুত, যা এখানে বড় লুপগুলির মধ্যে উল্লেখযোগ্য হতে পারে।
দশ

57
@ রবার্টডেইলি: এটি একটি সংকলক অপটিমাইজেশন এবং এটি আর সত্য নয়। আমি কেবল আমার বিশ্বাস যাচাই করার জন্য পরীক্ষা করেছি: যদি i ++ এর রিটার্ন মানটি কোনও কিছুর জন্য ব্যবহার না করা হয়, তবে সংকলক এটি আপনার জন্য স্বয়ংক্রিয়ভাবে ++ i হিসাবে সংকলন করবে। এছাড়াও, আমি যখন রিটার্ন মানটি ব্যবহার করি তখনও পারফরম্যান্সের পার্থক্যটি এত ছোট it এটি পরিমাপ করার জন্য আমার একটি চরম কেস তৈরি করা দরকার। তারপরেও এর ফলস্বরূপ মাত্র কয়েক শতাংশ ভিন্ন রানটাইম ছিল।
এডওয়ার্ড নেড হার্ভে

8
আমি ভালো একটি এক্সটেনশন পদ্ধতি লিখেছিলেন কিন্তু আমি এটা মূল অ্যারের আসতে ছিল যেমন chaining পদ্ধতির জন্য অনুমতি:int[] arr = new int[16].Populate(-1);
Gutblender

2
পরিবর্তন voidকরুন T[]এবং তারপরে আপনি যা করতে পারেনvar a = new int[100].Polupate(1)
16'50 এ ওরেড

198
Enumerable.Repeat(true, 1000000).ToArray();

70
যদিও এটি কাজ করে এটি সত্যিই ভাল সমাধান নয় কারণ এটি খুব ধীর; এটি আসলে লুপের সাথে পুনরাবৃত্ত হওয়ার চেয়ে প্রায় 4 গুণ ধীর।
patjbs

4
হ্যাঁ এটি সত্য, যখন আমরা পারফরম্যান্সকে লুপের জন্য দ্রুত বিবেচনা করি
রনি

6
কিছু আসল মাপদণ্ড দেখতে সি # ইনিশিয়াল অ্যারে দেখুন
থিঙ্কট

4
Enumerable.ToArrayসংখ্যাযুক্ত ক্রমের আকার জানেন না, সুতরাং এটি অ্যারের আকার হিসাবে অনুমান করতে হবে। এর অর্থ আপনি প্রতিটি বারের ToArrayবাফার ছাড়িয়ে গেলে অ্যারের বরাদ্দ পাবেন , ততক্ষণে ট্রিমের জন্য আরও একটি বরাদ্দ। অগণিত বস্তুর সাথে ওভারহেড জড়িত রয়েছে।
এডওয়ার্ড ব্রে

5
কেবল একটি নোট, যে রেফারেন্স টাইপ সহ এটি একই অ্যারেজেক্টের সমস্ত রেফারেন্স সহ পুরো অ্যারে পূরণ করবে। যদি আপনি যা চান তা না হয় এবং আপনি প্রতিটি অ্যারে আইটেমের জন্য প্রকৃতপক্ষে বিভিন্ন অবজেক্ট তৈরি করতে চান তবে stackoverflow.com/a/44937053/23715 দেখুন
অ্যালেক্স চে

74

হাজার trueমান সহ একটি নতুন অ্যারে তৈরি করুন :

var items = Enumerable.Repeat<bool>(true, 1000).ToArray();  // Or ToList(), etc.

একইভাবে, আপনি পূর্ণসংখ্যার ক্রম তৈরি করতে পারেন:

var items = Enumerable.Range(0, 1000).ToArray();  // 0..999

8
খারাপ নয়, তবে এটি 4x এর একটি ফ্যাক্টর দ্বারা লুপের চেয়ে এখনও ধীর
পাটজবস

1
ভবিষ্যতে তাত্ত্বিক হিসাবে গণ্য হবে patjbs.পরিবর্তন দ্রুত সম্পাদন করবে কারণ এটি একটি সমান্তরাল বাস্তবায়ন ব্যবহার করবে।
পেটার পেট্রোভ

1
@ পিটারপেট্রভ- ক্যাশে মারার কারণে এটি কখনই ঘটবে না। আমি মোটামুটি নিশ্চিত যে সিপিইউ ক্যাশের প্রকৃতির কারণে, একটি একক অ্যারেতে সমান্তরালে কাজ সম্পাদন করা সবসময়ই ধীর হবে কারণ কম্পিউটার সিঙ্ক্রোনাস কাজ আশা করে এবং সঠিকভাবে ডেটা লোড করে।
টেরনারি টোপরিয়ার

উদ্দেশ্যমূলক হতাশা! = অকাল অপ্টিমাইজেশনের অভাব।
ডেনিস গ্ল্যাডকি

24

বড় অ্যারে বা অ্যারেগুলির জন্য যা ভেরিয়েবল আকারের হতে পারে আপনার সম্ভবত ব্যবহার করা উচিত:

Enumerable.Repeat(true, 1000000).ToArray();

ছোট অ্যারের জন্য আপনি সংগ্রহের সূচনা সিনট্যাক্স সি # 3 এ ব্যবহার করতে পারেন:

bool[] vals = new bool[]{ false, false, false, false, false, false, false };

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

bool[] vals = new bool[]{ false, true, false, !(a ||b) && c, SomeBoolMethod() };

এবং একটি ভাসা শুরু করতে [] অ্যারে:float[] AlzCalDefault = new float[] {(float) 0.5, 18, 500, 1, 0};
জিম লাহমান

একটি অ্যারের FWIW প্রারম্ভিককরণ সি # এর মতো যে কোনও সংস্করণে করা যেতে পারে:bool[] vals = { false, true, false, !(a || b) && c, SomeBoolMethod() };
পিটার ভ্যান ডের হেইজডেন

24

আপনার অ্যারেটি যদি বড় হয় তবে আপনার বিটআরে ব্যবহার করা উচিত। এটি প্রতি বুলের জন্য বাইটের পরিবর্তে প্রতিটি বিলের জন্য 1 বিট ব্যবহার করে (যেমন বুলের অ্যারের মতো) আপনি বিট অপারেটরগুলির সাহায্যে সমস্ত বিটকে সত্যতে সেট করতে পারেন। বা ঠিক সত্যে আরম্ভ করুন। আপনার যদি একবার এটি করার দরকার হয় তবে এটির জন্য আরও বেশি ব্যয় হবে।

System.Collections.BitArray falses = new System.Collections.BitArray(100000, false);
System.Collections.BitArray trues = new System.Collections.BitArray(100000, true);

// Now both contain only true values.
falses.And(trues);

17

আপনি Array.Fill.NET কোর 2.0+ এবং .NET স্ট্যান্ডার্ড 2.1+ এ ব্যবহার করতে পারেন ।


অসাধারণ! যদিও সচেতন হোন যে এটি তুলনামূলকভাবে নতুন পদ্ধতি। এটা তোলে .NET কোর 2.0+ এবং .NET স্ট্যান্ডার্ড 2.1 পাওয়া যায়, কিন্তু বিশেষভাবে না .NET ফ্রেমওয়ার্ক সংস্করণ কোন। (এটি। নেট 5.0 এ থাকবে, যা। নেট ফ্রেমওয়ার্ক এবং। নেট কোর একসাথে মিশে থাকে)।
আবেল

9

দুর্ভাগ্যক্রমে আমি মনে করি না যে এখানে সরাসরি উপায় আছে তবে আমি মনে করি এটি করার জন্য আপনি অ্যারে শ্রেণীর জন্য একটি এক্সটেনশন পদ্ধতি লিখতে পারেন

class Program
{
    static void Main(string[] args)
    {
        int[] arr = new int[1000];
        arr.Init(10);
        Array.ForEach(arr, Console.WriteLine);
    }
}

public static class ArrayExtensions
{
    public static void Init<T>(this T[] array, T defaultVaue)
    {
        if (array == null)
            return;
        for (int i = 0; i < array.Length; i++)
        {
            array[i] = defaultVaue;
        }
    }
}

আমি এর মধ্যে যত বেশি খনন করি এক্সটেনশন ধারণাটি আমি পছন্দ করছি। কখনও কখনও আপফ্রন্ট এবং সহজ সমাধান সত্যিই সেরা!
patjbs

8

ঠিক আছে আরও কিছুটা গুগল করা এবং পড়ার পরে আমি এটি পেয়েছি:

bool[] bPrimes = new bool[1000000];
bPrimes = Array.ConvertAll<bool, bool>(bPrimes, b=> b=true);

যা অবশ্যই আমি যা খুঁজছি তার কাছাকাছি। তবে আমি নিশ্চিত নই যে এটি ফর-লুপে মূল অ্যারের মাধ্যমে পুনরাবৃত্তি করা এবং মানগুলি পরিবর্তন করার চেয়ে ভাল। প্রকৃতপক্ষে একটি দ্রুত পরীক্ষার পরে, এটি প্রায় 5 এর একটি ফ্যাক্টর দ্বারা ধীর হয়ে যায় So সুতরাং আসলে কোনও ভাল সমাধান তখন নয়!


4
এটি আপনার অ্যারেতে প্রতিটি উপাদানগুলির জন্য একটি ফাংশন কল করা ছাড়া আপনি যা করতে চাইছেন তার অনুরূপ। এটি সিন্ট্যাক্টিকভাবে অনেক সুন্দর
লাগছে

হ্যাঁ, এটি লুপের মতো একটি
সরল চেহারা

এটি একটি নতুন অ্যারে তৈরি করে (মূল উদাহরণটি পরিবর্তন করে না)।
জেপ্প স্টিগ নীলসন

7

একটি সমান্তরাল বাস্তবায়ন সম্পর্কে কি

public static void InitializeArray<T>(T[] array, T value)
{
    var cores = Environment.ProcessorCount;

    ArraySegment<T>[] segments = new ArraySegment<T>[cores];

    var step = array.Length / cores;
    for (int i = 0; i < cores; i++)
    {
        segments[i] = new ArraySegment<T>(array, i * step, step);
    }
    var remaining = array.Length % cores;
    if (remaining != 0)
    {
        var lastIndex = segments.Length - 1;
        segments[lastIndex] = new ArraySegment<T>(array, lastIndex * step, array.Length - (lastIndex * step));
    }

    var initializers = new Task[cores];
    for (int i = 0; i < cores; i++)
    {
        var index = i;
        var t = new Task(() =>
        {
            var s = segments[index];
            for (int j = 0; j < s.Count; j++)
            {
                array[j + s.Offset] = value;
            }
        });
        initializers[i] = t;
        t.Start();
    }

    Task.WaitAll(initializers);
}

যখন কেবল কোনও অ্যারের সূচনা করার সময় এই কোডটির শক্তি দেখা যায় না তবে আমি মনে করি আপনার অবশ্যই "বিশুদ্ধ" এর জন্য ভুলে যাওয়া উচিত।


এটি মিথ্যা ভাগ করে নেওয়ার বিষয়টি ঝুঁকিপূর্ণ করে, এতে বিভিন্ন থ্রেড সিপিইউ ক্যাশে লাইনের জন্য প্রতিযোগিতা করে এবং তাই একক থ্রেডযুক্ত প্রয়োগের তুলনায় কর্মক্ষমতা হ্রাস করে। এটি ঘটে কিনা প্রতি থ্রেড মেমরি ব্লক এবং সিপিইউ আর্কিটেকচারের আকারের উপর নির্ভর করে।
এরিক জে।

7

নীচের কোডটি ছোট অনুলিপিগুলির জন্য সাধারণ পুনরাবৃত্তি এবং বড় কপির জন্য অ্যারে.কপি সংযুক্ত করে

    public static void Populate<T>( T[] array, int startIndex, int count, T value ) {
        if ( array == null ) {
            throw new ArgumentNullException( "array" );
        }
        if ( (uint)startIndex >= array.Length ) {
            throw new ArgumentOutOfRangeException( "startIndex", "" );
        }
        if ( count < 0 || ( (uint)( startIndex + count ) > array.Length ) ) {
            throw new ArgumentOutOfRangeException( "count", "" );
        }
        const int Gap = 16;
        int i = startIndex;

        if ( count <= Gap * 2 ) {
            while ( count > 0 ) {
                array[ i ] = value;
                count--;
                i++;
            }
            return;
        }
        int aval = Gap;
        count -= Gap;

        do {
            array[ i ] = value;
            i++;
            --aval;
        } while ( aval > 0 );

        aval = Gap;
        while ( true ) {
            Array.Copy( array, startIndex, array, i, aval );
            i += aval;
            count -= aval;
            aval *= 2;
            if ( count <= aval ) {
                Array.Copy( array, startIndex, array, i, count );
                break;
            }
        }
    }

কোনও int [] অ্যারে ব্যবহার করে বিভিন্ন অ্যারে দৈর্ঘ্যের মানদণ্ডগুলি হ'ল:

         2 Iterate:     1981 Populate:     2845
         4 Iterate:     2678 Populate:     3915
         8 Iterate:     4026 Populate:     6592
        16 Iterate:     6825 Populate:    10269
        32 Iterate:    16766 Populate:    18786
        64 Iterate:    27120 Populate:    35187
       128 Iterate:    49769 Populate:    53133
       256 Iterate:   100099 Populate:    71709
       512 Iterate:   184722 Populate:   107933
      1024 Iterate:   363727 Populate:   126389
      2048 Iterate:   710963 Populate:   220152
      4096 Iterate:  1419732 Populate:   291860
      8192 Iterate:  2854372 Populate:   685834
     16384 Iterate:  5703108 Populate:  1444185
     32768 Iterate: 11396999 Populate:  3210109

প্রথম কলামগুলি অ্যারের আকার হয়, তারপরে একটি সাধারণ পুনরাবৃত্তি (@ জয়ারডেপড বাস্তবায়ন) ব্যবহার করে অনুলিপি করা হয়। এই পদ্ধতির সময় তার পরে। এই চারটি পূর্ণসংখ্যার কাঠামোর অ্যারে ব্যবহার করে মানদণ্ড

         2 Iterate:     2473 Populate:     4589
         4 Iterate:     3966 Populate:     6081
         8 Iterate:     7326 Populate:     9050
        16 Iterate:    14606 Populate:    16114
        32 Iterate:    29170 Populate:    31473
        64 Iterate:    57117 Populate:    52079
       128 Iterate:   112927 Populate:    75503
       256 Iterate:   226767 Populate:   133276
       512 Iterate:   447424 Populate:   165912
      1024 Iterate:   890158 Populate:   367087
      2048 Iterate:  1786918 Populate:   492909
      4096 Iterate:  3570919 Populate:  1623861
      8192 Iterate:  7136554 Populate:  2857678
     16384 Iterate: 14258354 Populate:  6437759
     32768 Iterate: 28351852 Populate: 12843259

7

বা ... আপনি কেবল উল্টানো যুক্তি ব্যবহার করতে পারেন। এর falseঅর্থ trueএবং বিপরীত।

কোড নমুনা

// bool[] isVisible = Enumerable.Repeat(true, 1000000).ToArray();
bool[] isHidden = new bool[1000000]; // Crazy-fast initialization!

// if (isVisible.All(v => v))
if (isHidden.All(v => !v))
{
    // Do stuff!
}

মজার সমাধান, যদিও এটি উদাহরণস্বরূপ
ইনটসের

1
পরিবর্তে: এই আসলে একটি টেকসই বিকল্প যদি আপনি পরিবর্তনশীল নামের উপর "যুক্তিবিজ্ঞান বিপরীতমুখী" হয় bool[] isVisibleএটিকেbool[] isHidden
মার্কুস Hütter

1
লোকেরা এই জাতীয় প্রতিক্রিয়া বলে মনে হচ্ছে এটি একরকম মজাদার হ্যাক। এটি একটি সাধারণ অপ্টিমাইজেশন কৌশল। আপনি যদি ভাগ্যবান হন তবে সংকলকটি এটি আপনার জন্য করবে।
l33t

4

এটিও কাজ করে ... তবে এটি অপ্রয়োজনীয় হতে পারে

 bool[] abValues = new bool[1000];
 abValues = abValues.Select( n => n = true ).ToArray<bool>();

4

এখানে উপস্থাপিত অনেকগুলি উত্তর এমন এক লুপে সিদ্ধ হয় যা একবারে অ্যারে এক উপাদানকে আরম্ভ করে, যা একবারে মেমরির ব্লকে পরিচালনা করার জন্য তৈরি সিপিইউ নির্দেশাবলীর সুবিধা নেয় না।

নেট স্ট্যান্ডার্ড 2.1 (এই লেখার হিসাবে প্রিভিউ) প্রদান করে Array.Fill () , যা নিজেই রানটাইম লাইব্রেরি একটি উচ্চ ক্ষমতা সম্পন্ন বাস্তবায়নে ধার দেয় (যদিও এখন থেকে, .NET কোর বলে মনে হচ্ছে না লিভারেজ যে সম্ভাবনা) ।

পূর্ববর্তী প্ল্যাটফর্মগুলির ক্ষেত্রে, অ্যারের আকারটি উল্লেখযোগ্য হলে নিম্নলিখিত এক্সটেনশন পদ্ধতিটি একটি উল্লেখযোগ্য মার্জিন দ্বারা একটি তুচ্ছ লুপকে ছাড়িয়ে যায়। বরাদ্দকৃত সময় বাজেটের চেয়ে যখন অনলাইন কোড চ্যালেঞ্জের জন্য আমার সমাধান প্রায় 20% ছিল তখনই আমি এটি তৈরি করেছি। এটি রানটাইমটিকে প্রায় 70% কমানো হয়েছিল। এই ক্ষেত্রে, অ্যারে ফিল অন্য লুপের ভিতরে সঞ্চালিত হয়েছিল। BLOCK_SIZE পরীক্ষা না করে অন্ত্রে অনুভূতি দ্বারা সেট করা হয়েছিল। কিছু অপ্টিমাইজেশন সম্ভব (যেমন একটি নির্দিষ্ট আকারের ব্লকের পরিবর্তে পছন্দসই মানটিতে ইতিমধ্যে সেট করা সমস্ত বাইট অনুলিপি করা)।

internal const int BLOCK_SIZE = 256;
public static void Fill<T>(this T[] array, T value)
{
    if (array.Length < 2 * BLOCK_SIZE)
    {
        for (int i = 0; i < array.Length; i++) array[i] = value;
    }
    else
    {
        int fullBlocks = array.Length / BLOCK_SIZE;
        // Initialize first block
        for (int j = 0; j < BLOCK_SIZE; j++) array[j] = value;
        // Copy successive full blocks
        for (int blk = 1; blk < fullBlocks; blk++)
        {
            Array.Copy(array, 0, array, blk * BLOCK_SIZE, BLOCK_SIZE);
        }

        for (int rem = fullBlocks * BLOCK_SIZE; rem < array.Length; rem++)
        {
            array[rem] = value;
        }
    }
}

3

আপনি যদি অ্যারেতে কেবল কয়েকটি মান সেট করার পরিকল্পনা করে থাকেন তবে বেশিরভাগ সময় (কাস্টম) ডিফল্ট মান পেতে চান তবে আপনি এরকম কিছু চেষ্টা করতে পারেন:

public class SparseArray<T>
{
    private Dictionary<int, T> values = new Dictionary<int, T>();

    private T defaultValue;

    public SparseArray(T defaultValue)
    {
        this.defaultValue = defaultValue;
    }

    public T this [int index]
    {
      set { values[index] = value; }
      get { return values.ContainsKey(index) ? values[index] ? defaultValue; }
    }
}

আপনাকে সম্ভবত অন্যান্য ইন্টারফেসগুলি কার্যকর করার জন্য এটি প্রয়োগ করতে হবে যেমন অ্যারে নিজেই রয়েছে।


3

অ্যারেতে সমস্ত উপাদানকে একক ক্রিয়াকলাপ হিসাবে নির্ধারণ করার উপায় নেই, ইউএনএলএসএলএস, মানটি হ'ল উপাদান ধরণের ডিফল্ট মান।

উদাহরণস্বরূপ, এটি যদি পূর্ণসংখ্যার অ্যারে হয় তবে আপনি একটি একক ক্রিয়াকলাপের মাধ্যমে সেগুলি সমস্তকে শূন্যতে সেট করতে পারেন: Array.Clear(...)


2

আমি বুঝতে পারলাম আমি পার্টিতে দেরি করেছি তবে এখানে একটি ধারণা আছে। একটি মোড়ক লিখুন যার মধ্যে মোড়কের মান থেকে এবং রূপান্তরকারী অপারেটর রয়েছে যাতে এটি মোড়ানো প্রকারের জন্য স্ট্যান্ড-ইন হিসাবে ব্যবহার করা যায়। এটি আসলে @ l33t এর নির্বোধ-উত্তরের উত্তর দ্বারা অনুপ্রাণিত হয়েছিল।

প্রথম (সি ++ থেকে আগত) আমি বুঝতে পেরেছিলাম যে সি # তে যখন অ্যারের উপাদানগুলি তৈরি করা হয় তখন ডিফল্ট কর্টর বলা হয় না। পরিবর্তে - এমনকি কোনও ব্যবহারকারী-সংজ্ঞায়িত ডিফল্ট নির্মাণকারীর উপস্থিতিতে! - সমস্ত অ্যারের উপাদানগুলি শূন্য-আরম্ভ হয়। এটা আমাকে অবাক করে দিয়েছিল।

সুতরাং একটি মোড়কের ক্লাস যা কেবল পছন্দসই মান সহ একটি ডিফল্ট কর্টর সরবরাহ করে তা সি ++ এ অ্যারেগুলির জন্য কাজ করবে তবে সি # তে নয়। রূপসীকরণের পরে মোড়ক প্রকারের মানচিত্রটিকে পছন্দসই বীজের মান 0 এ দেওয়া উচিত work এই পদ্ধতিতে শূন্য শুরুর মানগুলি সমস্ত ব্যবহারিক উদ্দেশ্যে বীজের সাথে আরম্ভ করা হবে বলে মনে হয়:

public struct MyBool
{
    private bool _invertedValue;

    public MyBool(bool b) 
    {   
        _invertedValue = !b;
    }

    public static implicit operator MyBool(bool b)
    {
        return new MyBool(b);
    }

    public static implicit operator bool(MyBool mb)
    {
        return !mb._invertedValue;
    }

}

static void Main(string[] args)
{
        MyBool mb = false; // should expose false.
        Console.Out.WriteLine("false init gives false: " 
                              + !mb);

        MyBool[] fakeBoolArray = new MyBool[100];

        Console.Out.WriteLine("Default array elems are true: " 
                              + fakeBoolArray.All(b => b) );

        fakeBoolArray[21] = false;
        Console.Out.WriteLine("Assigning false worked: " 
                              + !fakeBoolArray[21]);

        fakeBoolArray[21] = true;
        // Should define ToString() on a MyBool,
        // hence the !! to force bool
        Console.Out.WriteLine("Assigning true again worked: " 
                              + !!fakeBoolArray[21]);
}

এই ধরণটি সমস্ত মান ধরণের ক্ষেত্রে প্রযোজ্য। উদাহরণস্বরূপ, 4 টি দিয়ে ইনিশিয়ালেশন ইত্যাদির প্রয়োজন হলে ইনটগুলির জন্য 0 থেকে 4 ম্যাপ মানচিত্রের জন্য পারে etc.

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

FWIW, এখানে একটি সি ++ সমতুল্য: https://ideone.com/wG8yEh


2

যদি আপনি আপনার যুক্তিটি উল্টাতে পারেন তবে আপনি Array.Clear()বুলিয়ান অ্যারেটিকে মিথ্যাতে সেট করতে এই পদ্ধতিটি ব্যবহার করতে পারেন ।

        int upperLimit = 21;
        double optimizeMe = Math.Sqrt(upperLimit);

        bool[] seiveContainer = new bool[upperLimit];
        Array.Clear(seiveContainer, 0, upperLimit);

2

আপনি যদি নেট নেট, .NET স্ট্যান্ডার্ড> = 2.1 এ থাকেন বা সিস্টেমের উপর নির্ভর করে depend স্মৃতি প্যাকেজ, আপনি এই Span<T>.Fill()পদ্ধতিটিও ব্যবহার করতে পারেন :

var valueToFill = 165;
var data = new int[100];

data.AsSpan().Fill(valueToFill);

// print array content
for (int i = 0; i < data.Length; i++)
{
    Console.WriteLine(data[i]);
}

https://dotnetfiddle.net/UsJ9bu


2

মাইক্রোসফ্ট দ্বারা পরিত্যক্ত ফ্রেমওয়ার্ক ব্যবহারকারীরা এখানে আমাদের জন্য অন্য সংস্করণ। এটা তোলে যত দ্রুত 4 বার হয় Array.Clearএবং দ্রুত তুলনায় প্যানোগুলি Theof এর সমাধান এবং এরিক জে এর এবং Petar পেট্রোভ এর সমান্তরাল এক দুই বার ফাস্ট বৃহৎ অ্যারে হিসাবে -।

প্রথমে আমি আপনাকে ফাংশনের পূর্বপুরুষকে উপস্থাপন করতে চাই, কারণ এটি কোডটি বোঝা সহজ করে তোলে। প্যানোস থিওফের কোডের সাথে সামঞ্জস্যপূর্ণ পারফরম্যান্স-ভিত্তিক এবং এমন কিছু জিনিসের জন্য যা ইতিমধ্যে যথেষ্ট হতে পারে:

public static void Fill<T> (T[] array, int count, T value, int threshold = 32)
{
    if (threshold <= 0)
        throw new ArgumentException("threshold");

    int current_size = 0, keep_looping_up_to = Math.Min(count, threshold);

    while (current_size < keep_looping_up_to)
        array[current_size++] = value;

    for (int at_least_half = (count + 1) >> 1; current_size < at_least_half; current_size <<= 1)
        Array.Copy(array, 0, array, current_size, current_size);

    Array.Copy(array, 0, array, current_size, count - current_size);
}

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

const int ARRAY_COPY_THRESHOLD = 32;  // 16 ... 64 work equally well for all tested constellations
const int L1_CACHE_SIZE = 1 << 15;

public static void Fill<T> (T[] array, int count, T value, int element_size)
{
    int current_size = 0, keep_looping_up_to = Math.Min(count, ARRAY_COPY_THRESHOLD);

    while (current_size < keep_looping_up_to)
        array[current_size++] = value;

    int block_size = L1_CACHE_SIZE / element_size / 2;
    int keep_doubling_up_to = Math.Min(block_size, count >> 1);

    for ( ; current_size < keep_doubling_up_to; current_size <<= 1)
        Array.Copy(array, 0, array, current_size, current_size);

    for (int enough = count - block_size; current_size < enough; current_size += block_size)
        Array.Copy(array, 0, array, current_size, block_size);

    Array.Copy(array, 0, array, current_size, count - current_size);
}

দ্রষ্টব্য: (count + 1) >> 1দ্বিগুণ লুপের সীমা হিসাবে পূর্ববর্তী কোডের প্রয়োজনীয়তাটি নিশ্চিত করতে চূড়ান্ত অনুলিপি অপারেশনটিতে যে সমস্ত বাকী রয়েছে তা coverাকতে পর্যাপ্ত পরিমাণে চোর রয়েছে। এটির count >> 1পরিবর্তে যদি ব্যবহার করা হয় তবে বিজোড় সংখ্যাগুলির ক্ষেত্রে এটি হবে না । বর্তমান সংস্করণের জন্য এটি কোনও তাত্পর্যপূর্ণ নয় যেহেতু রৈখিক অনুলিপি লুপ যে কোনও স্লোকে তুলবে।

একটি অ্যারে ঘরের আকার অবশ্যই প্যারামিটার হিসাবে পাস করতে হবে কারণ - মাইন্ড বগলস - জেনেরিকগুলি ব্যবহার করতে অনুমতি দেয় sizeofনা যদি না তারা সীমাবদ্ধতা ( unmanaged) ব্যবহার করে যা ভবিষ্যতে উপলব্ধ নাও হতে পারে। ভুল অনুমানগুলি কোনও বড় বিষয় নয় তবে নিম্নলিখিত কারণগুলির জন্য মানটি সঠিক হলে কর্মক্ষমতা সর্বোত্তম:

  • উপাদানের আকারকে অবমূল্যায়ন করার ফলে L1 ক্যাশের অর্ধেকেরও বেশি আকারের ব্লক মাপগুলি বাড়ে, ফলে অনুলিপি উত্সের ডেটা L1 থেকে উচ্ছেদ হওয়ার সম্ভাবনা বাড়ায় এবং ধীর ক্যাশে স্তর থেকে পুনরায় আনতে হবে।

  • সিপিইউর এল 1 ক্যাশে আন্ডার-ইউজিলিমেটেড উপাদান আকারের পর্যালোচনা করা, মানে লিনিয়ার ব্লক কপি লুপটি সর্বোত্তম ব্যবহারের চেয়ে প্রায়শই কার্যকর হয় exec সুতরাং, কঠোরভাবে প্রয়োজনের তুলনায় স্থির লুপ / ​​কল ওভারহেডের বেশি।

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

array size   Array.Clear      Eric J.   Panos Theof  Petar Petrov   Darth Gizka
-------------------------------------------------------------------------------
     1000:       0,7 µs        0,2 µs        0,2 µs        6,8 µs       0,2 µs 
    10000:       8,0 µs        1,4 µs        1,2 µs        7,8 µs       0,9 µs 
   100000:      72,4 µs       12,4 µs        8,2 µs       33,6 µs       7,5 µs 
  1000000:     652,9 µs      135,8 µs      101,6 µs      197,7 µs      71,6 µs 
 10000000:    7182,6 µs     4174,9 µs     5193,3 µs     3691,5 µs    1658,1 µs 
100000000:   67142,3 µs    44853,3 µs    51372,5 µs    35195,5 µs   16585,1 µs 

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

দ্রষ্টব্য: ব্লকগুলি সাফ করা এবং পূরণ করা সাধারণত রানটাইম রুটিন দ্বারা সম্পন্ন হয় যা শাখাটি এমএমএক্স / এসএসই নির্দেশাবলী এবং হোয়াট নোট ব্যবহার করে অত্যন্ত বিশেষ কোডগুলিতে শাখা করে, সুতরাং যে কোনও শালীন পরিবেশে কোনও ব্যক্তি কেবল স্বতন্ত্র নৈতিক সমতুল্য কল করবে std::memsetএবং পেশাদার কর্মক্ষমতা স্তরের বিষয়ে নিশ্চিত হবে। আইওডাব্লু, অধিকার অনুসারে লাইব্রেরির ফাংশনটি Array.Clearআমাদের সমস্ত হাত-ঘূর্ণিত সংস্করণ ধূলিকণায় ফেলে রাখা উচিত। এটি অন্য উপায়ে যে ঘটনাটি ঘটে তা প্রকৃতপক্ষে দূর্বার বিষয়গুলির থেকে কতটা দূরে shows সবার Fill<>প্রথমে নিজের রোল করার জন্য একই কারণ এটি এখনও কেবলমাত্র কোর এবং স্ট্যান্ডার্ডে রয়েছে তবে ফ্রেমওয়ার্কে নয়। নেট প্রায় প্রায় বিশ বছর ধরে হয়েছে এবং আমাদের এখনও বেসিক স্টাফগুলির জন্য বাম এবং ডান পি / ইনভোক করতে হবে বা আমাদের নিজস্ব রোল করতে হবে ...


1

এই (সদৃশ?) প্রশ্নের আরও কিছু উত্তর রয়েছে: সি # তে মেমসেটের সমতুল্য কত?

কেউ বিকল্পগুলির বেঞ্চমার্ক করেছেন (তারা একটি অনিরাপদ সংস্করণ অন্তর্ভুক্ত করেছে, কিন্তু তারা চেষ্টা করেনি memset): http://techmikael.blogspot.co.uk/2009/12/filling-array-with-default-value.html


0

এখানে এমন আরও System.Collections.BitArrayএকটি কৌশল রয়েছে যার সাথে এই জাতীয় নির্মাতা রয়েছে।

bool[] result = new BitArray(1000000, true).Cast<bool>().ToArray();

অথবা

bool[] result = new bool[1000000];
new BitArray(1000000, true).CopyTo(result, 0);

0

আপনি অ্যারে তৈরি করেন তার ভিতরে একটি প্রাইভেট ক্লাস তৈরি করুন এবং এর জন্য একটি গেটর এবং সেটার রাখুন। আপনার অ্যারেতে প্রতিটি অবস্থানের প্রয়োজন না থাকলে এলোমেলো জাতীয় কিছু অনন্য হতে হবে, তারপরে ইনট ব্যবহার করবেন? একটি অ্যারের হিসাবে এবং তারপরে যদি অবস্থানটি সমান হয় তবে সেই অবস্থানটি পূরণ করুন এবং নতুন এলোমেলো মানটি ফিরিয়ে দিন।

IsVisibleHandler
{

  private bool[] b = new bool[10000];

  public bool GetIsVisible(int x)
  {
  return !b[x]
  }

  public void SetIsVisibleTrueAt(int x)
  {
  b[x] = false //!true
  }
}

বা ব্যবহার

public void SetIsVisibleAt(int x, bool isTrue)
{
b[x] = !isTrue;
}

সেটার হিসাবে


-2
Boolean[] data = new Boolean[25];

new Action<Boolean[]>((p) => { BitArray seed = new BitArray(p.Length, true); seed.CopyTo(p, 0); }).Invoke(data);

দয়া করে আরও ভাল ফর্ম্যাটিং এবং সম্ভবত কয়েকটি ব্যাখ্যাকারী শব্দ ব্যবহার করুন যাতে অন্যরা আপনার সমাধান আরও ভালভাবে বুঝতে পারে।
গর্জনসেগার

1
টার্গেট অ্যারে পার্টিশন করে এবং বিভিন্ন পার্টিশনে বীজ অনুলিপি করে আপনি আরম্ভের কর্মক্ষমতা বাড়াতে এটি ব্যবহার করতে পারেন। এটি কেবল একটি ধারণা দেওয়ার জন্যই ছিল - এটি আমার প্রথম এবং এটি আমার সর্বশেষ পোস্ট।
ldsmithperrin
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.