একটি নিয়মিত অ্যারের উপাদান সরান


135

আমার কাছে ফু অবজেক্টের একটি অ্যারে রয়েছে। অ্যারের দ্বিতীয় উপাদানটি আমি কীভাবে সরিয়ে ফেলব?

আমি RemoveAt()নিয়মিত অ্যারে জন্য অনুরূপ কিছু প্রয়োজন ।


1
ব্যবহার System.Collections.ObjectModel.Collection<Foo>
আবাটিশচেভ

1
আমার গেমের জন্য আমি একটি "নাল অ্যাটেক্স" ডেটাস্ট্রাকচার নিয়ে গিয়েছিলাম। মূলত, অভ্যন্তরীণ অ্যারে (বাফার) স্থির আকারের হয় এবং সূচি অপসারণ এবং অ্যারের আকার পরিবর্তন করার পরিবর্তে আমি কেবল সূচকটি নালায় পরিণত করি। যখন আমাকে কোনও আইটেম যুক্ত করতে হবে তখন আমি কেবল প্রথম অ-নাল সূচকটি খুঁজে পাই এবং এটি সেখানে রাখি। বেশ ভাল কাজ করে, তবে অবশ্যই সবকিছুর জন্য নয়।
ক্রিথিক

উত্তর:


202

আপনি যদি তালিকাটি ব্যবহার করতে না চান:

var foos = new List<Foo>(array);
foos.RemoveAt(index);
return foos.ToArray();

আপনি এই এক্সটেনশন পদ্ধতিটি চেষ্টা করতে পারেন যা আমি আসলে পরীক্ষা করে দেখিনি:

public static T[] RemoveAt<T>(this T[] source, int index)
{
    T[] dest = new T[source.Length - 1];
    if( index > 0 )
        Array.Copy(source, 0, dest, 0, index);

    if( index < source.Length - 1 )
        Array.Copy(source, index + 1, dest, index, source.Length - index - 1);

    return dest;
}

এবং এটি ব্যবহার করুন:

Foo[] bar = GetFoos();
bar = bar.RemoveAt(2);

8
এই উত্তরে প্রদত্ত প্রথম উদাহরণটি দ্বিতীয়টির তুলনায় অনেক কম দক্ষ। এটিতে দুটি নির্বাচনের অ্যারে অনুলিপি পরিবর্তে সূচকের পরে দুটি অ্যারের অনুলিপি এবং সমস্ত কিছুতে স্থানান্তরিত হওয়া দরকার।
মার্টিন ব্রাউন

2
অবশ্যই +1, তবে আমরা খুব বেশি তালিকাও ব্যবহার করতে পারি OR তালিকা <Foo> তালিকা = নতুন তালিকা <ফোল> (গেটফুস ()); list.Remove (my_foo); list.RemoveAt (2); যেখানে getFoos () ফুসের অ্যারে ফিরিয়ে দেবে !!!!
শাহজাপান

2
পদ্ধতির অভ্যন্তরের প্রথম লাইনে 'অ্যারে.লেনগথ' এর পরিবর্তে 'উত্স.লেন্থ' বলা উচিত।
নেলসন

1
এছাড়াও, মনে রাখবেন যে মূল অ্যারেতে কোনও রেফারেন্স সংরক্ষণ করে কোনও পরিবর্তনশীল মূল তথ্য ধারণ করতে থাকবে এবং উত্স এবং আউটপুট অ্যারের মধ্যে যে কোনও রেফারেন্স সমতা তুলনা একটি নেতিবাচক প্রত্যাবর্তন করবে।
বিকেকিসি

1
@ মার্টিনব্রাউন প্রকৃতপক্ষে, অ্যারের অনুলিপি (যা সিপিইউ দ্বারা অনুমোদিত কয়েকটি সর্বাধিক গতিতে ডেটা কেবল কয়েকটি ASM নির্দেশাবলী দিয়ে অনুলিপি করতে সক্ষম) থেকে আরে অ্যারে থেকে তালিকা রূপান্তর করা অনেক ধীর গতিতে রয়েছে। এছাড়াও একটি তালিকা স্থানান্তর করা খুব দ্রুত কারণ এটি কেবলমাত্র কয়েকটি পয়েন্টার অদলবদল এবং নোড ডেটা অপসারণ করার বিষয় (যা এই ক্ষেত্রে কেবল 8 বাইট [আরও বেশি 16 মাথার \ লেজ পয়েন্টারগুলির জন্য] এই ক্ষেত্রে)।
kroe2

66

অ্যারেগুলির প্রকৃতি হ'ল তাদের দৈর্ঘ্য অপরিবর্তনীয়। আপনি কোনও অ্যারে আইটেম যুক্ত বা মুছতে পারবেন না।

আপনাকে একটি নতুন অ্যারে তৈরি করতে হবে যা একটি উপাদান সংক্ষিপ্ত এবং আপনি যে উপাদানটি মুছতে চান তা বাদ দিয়ে পুরানো আইটেমগুলিকে নতুন অ্যারে অনুলিপি করতে হবে।

সুতরাং অ্যারের পরিবর্তে একটি তালিকা ব্যবহার করা ভাল।


4
অ্যারেটিকে একটি তালিকায় রূপান্তর করুনList<mydatatype> array = new List<mydatatype>(arrayofmydatatype)
অমর নীল

1
@ImmortalBlue বা কেবল নামস্থান থেকে পদ্ধতিটি var myList = myArray.ToList();ব্যবহার করুন । Enumerable.ToList()System.Linq
ডায়ান্ড্রিলিয়াক

58

আমি একটি অবজেক্ট অ্যারে থেকে উপাদান সরানোর জন্য এই পদ্ধতিটি ব্যবহার করি। আমার পরিস্থিতিতে আমার অ্যারেগুলি দৈর্ঘ্যে ছোট are সুতরাং আপনার যদি বড় অ্যারে থাকে তবে আপনার আর একটি সমাধানের প্রয়োজন হতে পারে।

private int[] RemoveIndices(int[] IndicesArray, int RemoveAt)
{
    int[] newIndicesArray = new int[IndicesArray.Length - 1];

    int i = 0;
    int j = 0;
    while (i < IndicesArray.Length)
    {
        if (i != RemoveAt)
        {
            newIndicesArray[j] = IndicesArray[i];
            j++;
        }

        i++;
    }

    return newIndicesArray;
}

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

1
এই উত্তরটি এত কম হওয়া সত্যিই লজ্জার বিষয়, যখন এটি উপরের দুটিটির চেয়ে আরও ভাল।
Sepulchritude

আড়হগ, এই যে উত্তরটি আমি খুঁজছিলাম! এটি তালিকা ছাড়াই সেরা পদ্ধতি।
জর্ডি হুয়ার্টাস

47

লাইনকিউ এক-লাইন সমাধান:

myArray = myArray.Where((source, index) => index != 1).ToArray();

1এই উদাহরণে, মূল প্রশ্ন অনুযায়ী, 2nd উপাদান (সঙ্গে - যে উদাহরণে অপসারণ উপাদান সূচক হয় 1সি # শূন্য ভিত্তিক অ্যারের ইন্ডেক্স দ্বিতীয় উপাদান হচ্ছে)।

আরও একটি সম্পূর্ণ উদাহরণ:

string[] myArray = { "a", "b", "c", "d", "e" };
int indexToRemove = 1;
myArray = myArray.Where((source, index) => index != indexToRemove).ToArray();

সেই স্নিপেট চালানোর পরে এর মান myArrayহবে { "a", "c", "d", "e" }


1
উচ্চতর কর্মক্ষমতা / ঘন ঘন অ্যাক্সেসের জন্য প্রয়োজনীয় ক্ষেত্রগুলির জন্য, লিনিকিউ প্রস্তাবিত নয়।
ক্রিথিক

3
@ ক্রাইথিক এটি একটি নিখুঁত মন্তব্য। একটি শক্ত লুপে হাজার বার চালান, এই পৃষ্ঠার আরও বেশ কয়েকটি ভোটযুক্ত
জন স্নাইডার

9

এটি অন্য অ্যারে অনুলিপি না করে .Net 3.5 হিসাবে কোনও অ্যারের উপাদানটি মুছে ফেলার একটি উপায় - এর সাথে একই অ্যারে উদাহরণটি ব্যবহার করে Array.Resize<T>:

public static void RemoveAt<T>(ref T[] arr, int index)
{
    for (int a = index; a < arr.Length - 1; a++)
    {
        // moving elements downwards, to fill the gap at [index]
        arr[a] = arr[a + 1];
    }
    // finally, let's decrement Array's size by one
    Array.Resize(ref arr, arr.Length - 1);
}

2
"অন্য অ্যারে অনুলিপি না করেই" - লিঙ্কযুক্ত ডকুমেন্টেশন অনুসারে অ্যারে। রিসাইজ আসলে পর্দার আড়ালে একটি নতুন অ্যারে বরাদ্দ করে এবং পুরানো অ্যারে থেকে উপাদানটিকে নতুনটিতে অনুলিপি করে। তবুও, আমি এই সমাধানটির সংক্ষিপ্ততা পছন্দ করি।
জন স্নাইডার

খুব সুন্দর এবং পরিষ্কার আপনি যদি নিশ্চিত হন যে এটি তুলনামূলকভাবে ছোট অ্যারে।
ড্যারেন

1
@ জোনস্কিনিডারের মন্তব্য অবিরত, এটি "একই অ্যারে উদাহরণ" নয়। যে কারণে আপনি refযখন Resizeপদ্ধতিটি কল করবেন তখন আপনাকে ব্যবহার করা দরকার । একটি অ্যারের উদাহরণ দৈর্ঘ্য স্থির এবং অপরিবর্তনীয়।
জেপ্পে স্টিগ নীলসন

2
যদি উপাদানগুলির ক্রমটি গুরুত্বপূর্ণ না হয়, সমস্ত উপাদানকে নীচে নিয়ে যাওয়ার পরিবর্তে আপনি উপাদানটি সূচকগুলিতে শেষ উপাদানটির সাথে পরিবর্তন করতে পারেন এবং তারপরে পুনরায় আকার দিন: আরর [সূচক] = আরআর [অ্যারেঞ্জার লেন্থ - ১]; অ্যারে.রাইসাইজ (রেফ আরার, এআরআর। দৈর্ঘ্য - 1);
বারটেল

5

এখানে আমার একটি পুরানো সংস্করণ রয়েছে যা .NET ফ্রেমওয়ার্কের 1.0 সংস্করণে কাজ করে এবং জেনেরিক ধরণের প্রয়োজন নেই।

public static Array RemoveAt(Array source, int index)
{
    if (source == null)
        throw new ArgumentNullException("source");

    if (0 > index || index >= source.Length)
        throw new ArgumentOutOfRangeException("index", index, "index is outside the bounds of source array");

    Array dest = Array.CreateInstance(source.GetType().GetElementType(), source.Length - 1);
    Array.Copy(source, 0, dest, 0, index);
    Array.Copy(source, index + 1, dest, index, source.Length - index - 1);

    return dest;
}

এটি এভাবে ব্যবহার করা হয়:

class Program
{
    static void Main(string[] args)
    {
        string[] x = new string[20];
        for (int i = 0; i < x.Length; i++)
            x[i] = (i+1).ToString();

        string[] y = (string[])MyArrayFunctions.RemoveAt(x, 3);

        for (int i = 0; i < y.Length; i++)
            Console.WriteLine(y[i]);
    }
}

3

এটি সম্পর্কে ঠিক যাবার উপায় নয়, তবে পরিস্থিতি যদি নগণ্য হয় এবং আপনি আপনার সময়কে মূল্য দেন, তবে আপনি এটিকে নালার জন্য চেষ্টা করতে পারেন।

Foos[index] = null

এবং পরে আপনার যুক্তিতে নাল প্রবেশের জন্য পরীক্ষা করুন ..


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

2

যথারীতি আমি পার্টিতে দেরি করেছি ...

আমি ইতিমধ্যে উপস্থিত দুর্দান্ত সমাধান তালিকায় আরেকটি বিকল্প যুক্ত করতে চাই। =)
আমি এটি এক্সটেনশনের জন্য একটি ভাল সুযোগ হিসাবে দেখতে চাই।

তথ্যসূত্র: http://msdn.microsoft.com/en-us/library/bb311042.aspx

সুতরাং, আমরা কিছু স্থির শ্রেণি সংজ্ঞায়িত করি এবং এটিতে আমাদের পদ্ধতি।
এর পরে, আমরা আমাদের বর্ধিত পদ্ধতিটি উইলি-নিলি ব্যবহার করতে পারি। =)

using System;

namespace FunctionTesting {

    // The class doesn't matter, as long as it's static
    public static class SomeRandomClassWhoseNameDoesntMatter {

        // Here's the actual method that extends arrays
        public static T[] RemoveAt<T>( this T[] oArray, int idx ) {
            T[] nArray = new T[oArray.Length - 1];
            for( int i = 0; i < nArray.Length; ++i ) {
                nArray[i] = ( i < idx ) ? oArray[i] : oArray[i + 1];
            }
            return nArray;
        }
    }

    // Sample usage...
    class Program {
        static void Main( string[] args ) {
            string[] myStrArray = { "Zero", "One", "Two", "Three" };
            Console.WriteLine( String.Join( " ", myStrArray ) );
            myStrArray = myStrArray.RemoveAt( 2 );
            Console.WriteLine( String.Join( " ", myStrArray ) );
            /* Output
             * "Zero One Two Three"
             * "Zero One Three"
             */

            int[] myIntArray = { 0, 1, 2, 3 };
            Console.WriteLine( String.Join( " ", myIntArray ) );
            myIntArray = myIntArray.RemoveAt( 2 );
            Console.WriteLine( String.Join( " ", myIntArray ) );
            /* Output
             * "0 1 2 3"
             * "0 1 3"
             */
        }
    }
}

2

কোড নীচে চেষ্টা করুন:

myArray = myArray.Where(s => (myArray.IndexOf(s) != indexValue)).ToArray();

অথবা

myArray = myArray.Where(s => (s != "not_this")).ToArray();

1

আমি এটি কীভাবে করেছি ...

    public static ElementDefinitionImpl[] RemoveElementDefAt(
        ElementDefinition[] oldList,
        int removeIndex
    )
    {
        ElementDefinitionImpl[] newElementDefList = new ElementDefinitionImpl[ oldList.Length - 1 ];

        int offset = 0;
        for ( int index = 0; index < oldList.Length; index++ )
        {
            ElementDefinitionImpl elementDef = oldList[ index ] as ElementDefinitionImpl;
            if ( index == removeIndex )
            {
                //  This is the one we want to remove, so we won't copy it.  But 
                //  every subsequent elementDef will by shifted down by one.
                offset = -1;
            }
            else
            {
                newElementDefList[ index + offset ] = elementDef;
            }
        }
        return newElementDefList;
    }

1

একটি সাধারণ অ্যারেতে আপনাকে 2 এর উপরে সমস্ত অ্যারের এন্ট্রিগুলি পরিবর্তন করতে হবে এবং তারপরে পুনরায় আকারের পদ্ধতিটি ব্যবহার করে এটি পুনরায় আকার দিতে হবে। আপনি অ্যারেলিস্ট ব্যবহার করে আরও ভাল হতে পারেন।


1
    private int[] removeFromArray(int[] array, int id)
    {
        int difference = 0, currentValue=0;
        //get new Array length
        for (int i=0; i<array.Length; i++)
        {
            if (array[i]==id)
            {
                difference += 1;
            }
        }
        //create new array
        int[] newArray = new int[array.Length-difference];
        for (int i = 0; i < array.Length; i++ )
        {
            if (array[i] != id)
            {
                newArray[currentValue] = array[i];
                currentValue += 1;
            }
        }

        return newArray;
    }

0

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

public static class Arr
{
    public static int IndexOf<TElement>(this TElement[] Source, TElement Element)
    {
        for (var i = 0; i < Source.Length; i++)
        {
            if (Source[i].Equals(Element))
                return i;
        }

        return -1;
    }

    public static TElement[] Add<TElement>(ref TElement[] Source, params TElement[] Elements)
    {
        var OldLength = Source.Length;
        Array.Resize(ref Source, OldLength + Elements.Length);

        for (int j = 0, Count = Elements.Length; j < Count; j++)
            Source[OldLength + j] = Elements[j];

        return Source;
    }

    public static TElement[] New<TElement>(params TElement[] Elements)
    {
        return Elements ?? new TElement[0];
    }

    public static void Remove<TElement>(ref TElement[] Source, params TElement[] Elements)
    {
        foreach (var i in Elements)
            RemoveAt(ref Source, Source.IndexOf(i));
    }

    public static void RemoveAt<TElement>(ref TElement[] Source, int Index)
    {
        var Result = new TElement[Source.Length - 1];

        if (Index > 0)
            Array.Copy(Source, 0, Result, 0, Index);

        if (Index < Source.Length - 1)
            Array.Copy(Source, Index + 1, Result, Index, Source.Length - Index - 1);

        Source = Result;
    }
}

পারফরম্যান্স অনুযায়ী, এটি শালীন, তবে এটি সম্ভবত উন্নত হতে পারে। Removeনির্ভর করে IndexOfএবং কল করে আপনি যে উপাদানটিকে সরাতে চান তার জন্য একটি নতুন অ্যারে তৈরি করা হয় RemoveAt

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

আমি Mergeদুটি অ্যারে মার্জ করার জন্য একটি পদ্ধতি সংজ্ঞায়িত করব ; তবে, ইতিমধ্যে Addএকাধিক, স্বতন্ত্র উপাদানগুলির তুলনায় একটি আসল অ্যারে পাস করে পদ্ধতিটি দ্বারা ইতিমধ্যে সম্পন্ন করা যেতে পারে । সুতরাং, Addউপাদান দুটি সেট যোগদানের জন্য নিম্নলিখিত দুটি উপায়ে ব্যবহার করা যেতে পারে:

Arr.Add<string>(ref myArray, "A", "B", "C");

অথবা

Arr.Add<string>(ref myArray, anotherArray);

-1

আমি জানি এই নিবন্ধটি দশ বছরের পুরানো এবং তাই সম্ভবত মৃত, তবে এখানে আমি যা করার চেষ্টা করব:

System.Linq এ পাওয়া IEnumerable.Sipip () পদ্ধতিটি ব্যবহার করুন । এটি অ্যারে থেকে নির্বাচিত উপাদানটি এড়িয়ে যাবে এবং অ্যারের অন্য একটি অনুলিপি প্রদান করবে যা কেবলমাত্র নির্বাচিত বস্তু ব্যতীত সমস্ত কিছু রয়েছে। তারপরে পুনরাবৃত্তি করুন যে প্রতিটি উপাদান আপনি মুছে ফেলতে চান এবং এর পরে এটি একটি ভেরিয়েবলে সংরক্ষণ করুন।

উদাহরণস্বরূপ, যদি আমাদের 5 টি সংখ্যার সাথে "নমুনা" (টাইপ int [] এর) নামের একটি অ্যারে থাকে। আমরা ২ য় নম্বর মুছে ফেলতে চাই, তাই "নমুনা.স্কিপ (2) চেষ্টা করে"; ২ য় নম্বর ব্যতীত একই অ্যারেটি ফেরত দেওয়া উচিত।


এই পদ্ধতিটি কি কেবল একটি ক্রমিকায় নির্দিষ্ট সংখ্যক উপাদানকে বাইপাস করে না এবং তারপরে অবশিষ্ট উপাদানগুলি ফেরত দেয় ? আপনার উদাহরণে আপনি জেনেরিক তালিকার প্রথম দুটি উপাদানকে "এড়িয়ে" যাবেন এবং কেবল ২ য় নয়!
xnr_z

-4

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

// Convert An array of string  to a list of string
public static List<string> ConnvertArrayToList(this string [] array) {

    // DECLARE a list of string and add all element of the array into it

    List<string> myList = new List<string>();
    foreach( string s in array){
        myList.Add(s);
    }
    return myList;
} 

দ্বিতীয় পদক্ষেপ
তালিকাটিকে অ্যারেতে রূপান্তর করতে একটি এক্সটেনশন পদ্ধতি লিখুন

// convert a list of string to an array 
public static string[] ConvertListToArray(this List<string> list) {

    string[] array = new string[list.Capacity];
    array = list.Select(i => i.ToString()).ToArray();
    return array;
}

শেষ পদক্ষেপগুলি
আপনার চূড়ান্ত পদ্ধতিটি লিখুন, তবে কোড শোয়ের মতো অ্যারেতে রূপান্তরিত করার আগে সূচকের উপাদানটি সরিয়ে ফেলার কথা মনে রাখবেন

public static string[] removeAt(string[] array, int index) {

    List<string> myList = array.ConnvertArrayToList();
    myList.RemoveAt(index);
    return myList.ConvertListToArray();
} 

উদাহরণ কোডগুলি আমার ব্লগে খুঁজে পেতে পারে , ট্র্যাকিং চালিয়ে যান।


13
এটি অস্তিত্ব .ToArray()এবং এমন কোনও List<T>নির্মাণকারীর কথা বিবেচনা করে হালকাভাবে উন্মাদ, যা বিদ্যমান ক্রম নেয় ...
ব্যবহারকারীর 1111
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.