কিভাবে সেরা উপায়ে তালিকা আইটেম প্রতিস্থাপন


103
if (listofelements.Contains(valueFieldValue.ToString()))
{
    listofelements[listofelements.IndexOf(valueFieldValue.ToString())] = value.ToString();
}

আমি উপরের মত প্রতিস্থাপন করেছি এই তুলনায় অন্য কোন সেরা ওয়ে আছে?

উত্তর:


115

তালিকায় সূচীটি পেতে ল্যাম্বদা ব্যবহার করুন এবং তালিকা আইটেমটি প্রতিস্থাপন করতে এই সূচিটি ব্যবহার করুন।

List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
listOfStrings[listOfStrings.FindIndex(ind=>ind.Equals("123"))] =  "def";

16
-1 এর জন্য চেক করুন! আইটেমটি সংগ্রহগুলিতে উপস্থিত না থাকলে
— সুরেন্দ্র সিং মালিক মালিক

4
আরও একটি ফাইন্ড ইন্ডেক্স ব্যবহারের জন্য
— অ্যারোন বার্কার

4
এটি সেরা সর্বজনীন উত্তর আইএমএইচও যেহেতু এটি বস্তুর তুলনা করতেও ব্যবহার করা যেতে পারে।
— সিমচা খাবিনস্কি

দেখুন Fej এর বর্ধিতকরণ যে জন্য -1 চেক । যদিও একটি সাধারণ Equalsপরীক্ষার জন্য, ভাল পুরানো IndexOfঠিক তেমনি কাজ করে এবং আরও সংক্ষিপ্ত - টিমের জবাব অনুসারে ।
— টুলমেকারস্টেভ

109

আপনি এটিকে আরও পঠনযোগ্য এবং আরও দক্ষ করে তুলতে পারেন:

string oldValue = valueFieldValue.ToString();
string newValue = value.ToString();
int index = listofelements.IndexOf(oldValue);
if(index != -1)
    listofelements[index] = newValue;

এটি সূচকের জন্য একবার জিজ্ঞাসা করে। আপনার পদ্ধতির Containsপ্রথমে ব্যবহার করে যা সমস্ত আইটেম লুপ করা প্রয়োজন (সবচেয়ে খারাপ ক্ষেত্রে), তারপরে আপনি IndexOfযা ব্যবহার করছেন তা আবার আইটেমগুলি গণনা করা প্রয়োজন।


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

4
@ সিমখাখাবিনস্কি: রেফারেন্সের ধরণের সাথেও কাজ করে, টাইপটি কেবল ওভাররাইড করা প্রয়োজন Equalsবা আপনি যদি কেবল একই জিনিসটি দেখতে পান তবে এটি কেবলমাত্র আবিষ্কার করতে পারেন। দ্রষ্টব্য stringএটিও একটি অবজেক্ট (রেফারেন্স টাইপ)।
— টিম শ্মেলেটার

হ্যাঁ তুমিই ঠিক. তবে, আমি অনেকগুলি বিকাশকারীকে প্রয়োগ করতে মনে করতে ব্যর্থ হতে দেখেছি Equals এবং আপনাকে এটিও মনে রাখতে হবে যে কখনও কখনও একই সময়ে আপনাকে প্রয়োগ করতে হয়GetHashCode
— সিমচা খবিনস্কি

4
@ সিম্যাখাবিনস্কি: হ্যাঁ, আপনি ওভাররাইড GetHashCodeকরলে আপনার সর্বদা ওভাররাইড করা উচিত Equalsতবে GetHashCodeকেবলমাত্র যদি বস্তুটি কোনও সেট (ফে Dictionaryবা HashSet) এ সংরক্ষণ করা হয় তবে কেবল এটি ব্যবহার করা হয় না IndexOfবা Containsকেবল ব্যবহৃত হয় Equals।
— টিম শ্মেলটার

টিম, আমার এই বনাম রকচুচান সম্পর্কে একটি প্রশ্ন আছে। আমি যে ডক্স পড়া IndexOfব্যবহারসমূহ EqualityComparer<T>.Default। আপনি কি বলছেন যে শেষ পর্যন্ত item.Equals(target)তালিকার প্রতিটি আইটেমের জন্য আহ্বান জানাবে , এবং তাই রোককুচনের উত্তরের মতোই একই আচরণ রয়েছে?
— টুলমেকারস্টেভ

16

একটি উপাদান প্রতিস্থাপন করতে আপনি আপনার তালিকাতে দুবার অ্যাক্সেস করছেন। আমি মনে করি সহজ forলুপটি যথেষ্ট হওয়া উচিত:

var key = valueFieldValue.ToString();
for (int i = 0; i < listofelements.Count; i++)
{
    if (listofelements[i] == key)
    {
        listofelements[i] = value.ToString();
        break;
    }
}

4
@gzaxx। "একটি উপাদান প্রতিস্থাপনের জন্য আপনি আপনার তালিকাতে দুবার অ্যাক্সেস করছেন I আমি মনে করি লুপের জন্য সহজ যথেষ্ট হওয়া উচিত"। এবং লুপ সাথীর জন্য আপনি কতবার তালিকাটি অ্যাক্সেস করতে পারেন?
— পাপ

4
@ প্যাপ দুঃখিত, আমি যথেষ্ট পরিষ্কার ছিল না। তিনি তার তালিকাটি দুবার পুনরাবৃত্তি করছেন (প্রথমে আইটেম তালিকার ভিতরে রয়েছে কিনা তা পরীক্ষা করে প্রথমে আইটেম সূচক পেতে দ্বিতীয়)।
— gzaxx

14

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

নিম্নলিখিত কোড বিবেচনা করুন:

        var intArray = new int[] { 0, 1, 1, 2, 3, 4 };
        // Replaces the first occurance and returns the index
        var index = intArray.Replace(1, 0);
        // {0, 0, 1, 2, 3, 4}; index=1

        var stringList = new List<string> { "a", "a", "c", "d"};
        stringList.ReplaceAll("a", "b");
        // {"b", "b", "c", "d"};

        var intEnum = intArray.Select(x => x);
        intEnum = intEnum.Replace(0, 1);
        // {0, 0, 1, 2, 3, 4} => {1, 1, 1, 2, 3, 4}
  • কোনও কোড সদৃশ
  • দীর্ঘ লিনক এক্সপ্রেশন টাইপ করার প্রয়োজন নেই
  • অতিরিক্ত ব্যবহারের দরকার নেই

উত্স কোড:

namespace System.Collections.Generic
{
    public static class Extensions
    {
        public static int Replace<T>(this IList<T> source, T oldValue, T newValue)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            var index = source.IndexOf(oldValue);
            if (index != -1)
                source[index] = newValue;
            return index;
        }

        public static void ReplaceAll<T>(this IList<T> source, T oldValue, T newValue)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            int index = -1;
            do
            {
                index = source.IndexOf(oldValue);
                if (index != -1)
                    source[index] = newValue;
            } while (index != -1);
        }


        public static IEnumerable<T> Replace<T>(this IEnumerable<T> source, T oldValue, T newValue)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            return source.Select(x => EqualityComparer<T>.Default.Equals(x, oldValue) ? newValue : x);
        }
    }
}

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

পিএস মাইকের পর্যবেক্ষণের জন্য ধন্যবাদ , আমি রিপ্লেসএল পদ্ধতিটি যুক্ত করেছি।


4
পুনরায় "স্থানে রেফারেন্সের ধরণের জিনিসগুলি পরিবর্তন করুন" - Tকোনও রেফারেন্স টাইপ কিনা তা অপ্রাসঙ্গিক। আপনি তালিকার পরিবর্তন করতে (পরিবর্তন করতে) বা একটি নতুন তালিকা ফিরে আসতে চান কিনা তা গুরুত্বপূর্ণ। অবশ্যই তৃতীয় পদ্ধতি মূল তালিকা পরিবর্তন করা হবে না, তাই আপনি করতে পারবেন না শুধু তৃতীয় পদ্ধতি ব্যবহার ... । প্রথম পদ্ধতিটি হ'ল যা জিজ্ঞাসা করা নির্দিষ্ট প্রশ্নের উত্তর দেয়। দুর্দান্ত কোড - কেবল পদ্ধতিগুলি কী করে তার আপনার বর্ণনাকে সংশোধন করে :)
— টুলমেকারস্টেভ

7

রোককুচের উত্তর অনুসরণ করে, সামান্য আপগ্রেড করুন:

List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};

int index = listOfStrings.FindIndex(ind => ind.Equals("123"));
if (index > -1)
    listOfStrings[index] =  "def";

5

FindIndexআপনার মানগুলি খুঁজে পেতে এবং প্রতিস্থাপন করতে ল্যাম্বডা ব্যবহার করুন :

int j = listofelements.FindIndex(i => i.Contains(valueFieldValue.ToString())); //Finds the item index

lstString[j] = lstString[j].Replace(valueFieldValue.ToString(), value.ToString()); //Replaces the item by new value

3

আপনি পরবর্তী এক্সটেনশানগুলি ব্যবহার করতে পারেন যা একটি পূর্বাভাস শর্তের উপর ভিত্তি করে:

    /// <summary>
    /// Find an index of a first element that satisfies <paramref name="match"/>
    /// </summary>
    /// <typeparam name="T">Type of elements in the source collection</typeparam>
    /// <param name="this">This</param>
    /// <param name="match">Match predicate</param>
    /// <returns>Zero based index of an element. -1 if there is not such matches</returns>
    public static int IndexOf<T>(this IList<T> @this, Predicate<T> match)
    {
        @this.ThrowIfArgumentIsNull();
        match.ThrowIfArgumentIsNull();

        for (int i = 0; i < @this.Count; ++i)
            if (match(@this[i]))
                return i;

        return -1;
    }

    /// <summary>
    /// Replace the first occurance of an oldValue which satisfies the <paramref name="removeByCondition"/> by a newValue
    /// </summary>
    /// <typeparam name="T">Type of elements of a target list</typeparam>
    /// <param name="this">Source collection</param>
    /// <param name="removeByCondition">A condition which decides is a value should be replaced or not</param>
    /// <param name="newValue">A new value instead of replaced</param>
    /// <returns>This</returns>
    public static IList<T> Replace<T>(this IList<T> @this, Predicate<T> replaceByCondition, T newValue)
    {
        @this.ThrowIfArgumentIsNull();
        removeByCondition.ThrowIfArgumentIsNull();

        int index = @this.IndexOf(replaceByCondition);
        if (index != -1)
            @this[index] = newValue;

        return @this;
    }

    /// <summary>
    /// Replace all occurance of values which satisfy the <paramref name="removeByCondition"/> by a newValue
    /// </summary>
    /// <typeparam name="T">Type of elements of a target list</typeparam>
    /// <param name="this">Source collection</param>
    /// <param name="removeByCondition">A condition which decides is a value should be replaced or not</param>
    /// <param name="newValue">A new value instead of replaced</param>
    /// <returns>This</returns>
    public static IList<T> ReplaceAll<T>(this IList<T> @this, Predicate<T> replaceByCondition, T newValue)
    {
        @this.ThrowIfArgumentIsNull();
        removeByCondition.ThrowIfArgumentIsNull();

        for (int i = 0; i < @this.Count; ++i)
            if (replaceByCondition(@this[i]))
                @this[i] = newValue;

        return @this;
    }

নোটস: - থ্রোএফআরগমেন্টমেন্টস নাল এক্সটেনশনের পরিবর্তে আপনি সাধারণ পদ্ধতির মতো ব্যবহার করতে পারেন:

if (argName == null) throw new ArgumentNullException(nameof(argName));

সুতরাং এই এক্সটেনশনগুলির সাথে আপনার কেস হিসাবে সমাধান করা যেতে পারে:

string targetString = valueFieldValue.ToString();
listofelements.Replace(x => x.Equals(targetString), value.ToString());

1

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

List<string> data = new List<string>
(new string[]   { "Computer", "A", "B", "Computer", "B", "A" });
int[] indexes = Enumerable.Range(0, data.Count).Where
                 (i => data[i] == "Computer").ToArray();
Array.ForEach(indexes, i => data[i] = "Calculator");

1

অথবা, রুশিয়ান এল এর পরামর্শ অনুযায়ী আপনি যে আইটেমটি অনুসন্ধান করছেন তা যদি তালিকার একাধিকবার হতে পারে তবে ::

[Extension()]
public void ReplaceAll<T>(List<T> input, T search, T replace)
{
    int i = 0;
    do {
        i = input.FindIndex(i, s => EqualityComparer<T>.Default.Equals(s, search));

        if (i > -1) {
            FileSystem.input(i) = replace;
            continue;
        }

        break;  
    } while (true);
}

1

আপনি এইভাবে ল্যাম্বডা এক্সপ্রেশন ব্যবহার করতে পারেন।

int index = listOfElements.FindIndex(item => item.Id == id);  
if (index != -1) 
{
    listOfElements[index] = newValue;
}

0

আমি এটি দ্রুত এবং সহজ করার জন্য সবচেয়ে ভাল খুঁজে পাই

  1. তালিকায় আপনার আইটেম সন্ধান করুন

    var d = Details.Where(x => x.ProductID == selectedProduct.ID).SingleOrDefault();
    
  2. বর্তমান থেকে ক্লোন তৈরি করুন

    OrderDetail dd = d;
    
  3. আপনার ক্লোন আপডেট করুন

    dd.Quantity++;
    
  4. তালিকায় সূচকটি সন্ধান করুন

    int idx = Details.IndexOf(d);
    
  5. প্রতিষ্ঠিত আইটেমটি সরান (1)

      Details.Remove(d);
    
  6. .োকান

     if (idx > -1)
          Details.Insert(idx, dd);
      else
          Details.Insert(Details.Count, dd);
    
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.