How to replace list item in best way

Solution 1:

Use Lambda to find the index in the List and use this index to replace the list item.

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

int index = listOfStrings.FindIndex(s => s == "123");

if (index != -1)
    listOfStrings[index] =  "def";

Solution 2:

You could make it more readable and more efficient:

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

This asks only once for the index. Your approach uses Contains first which needs to loop all items(in the worst case), then you're using IndexOf which needs to enumerate the items again .

Solution 3:

Why not use the extension methods?

Consider the following code:

        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}
  • No code duplication
  • There is no need to type long linq expressions
  • There is no need for additional usings

The source code:

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);
        }
    }
}

The first two methods have been added to change the objects of reference types in place. Of course, you can use just the third method for all types.

P.S. Thanks to mike's observation, I've added the ReplaceAll method.

Solution 4:

You are accessing your list twice to replace one element. I think simple for loop should be enough:

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

Solution 5:

Following rokkuchan's answer, just a little upgrade:

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

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