Как заменить элемент списка наилучшим образом


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

Я заменил как выше. Есть ли другой лучший способ для сравнения, чем этот?

9 56
c#

9 ответов:

вы могли бы сделать его более читаемым и более эффективным:

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

Это спрашивает только один раз для индекса. Ваш подход использует Contains сначала нужно зациклить все элементы (в худшем случае), затем вы используете IndexOf который должен перечислить элементы снова .

используйте лямбда, чтобы найти индекс в списке и использовать этот индекс для замены элемента списка.

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

вы обращаетесь к своему списку дважды, чтобы заменить один элемент. Я думаю, просто for петли должно быть достаточно:

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

почему бы не использовать методы расширения?

рассмотрим следующий код:

        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}
  • не дублировать код
  • нет необходимости вводить длинные выражения linq
  • нет необходимости в дополнительном использовании

исходный код:

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("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("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("source");

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

первые два метода были добавлены для изменения объектов ссылочных типов на месте. Конечно, вы можете использовать только третий способ для всех типы.

П. С. Спасибо Майка!--20-->, я добавил метод ReplaceAll.

использовать 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

Я не знаю, если это лучше или нет, но вы можете использовать его также

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

или, основываясь на предложении Rusian L., Если элемент, который вы ищете, может быть в списке более одного раза::

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

после ответа роккучана, просто небольшое обновление:

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

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

Я думаю, что лучше использовать ObservableCollection вместо List и преобразовать его в список, когда нам нужно его ранжировать. с observable collection вы можете удалить и добавить элемент в две строки, но вам нужно закодировать дюжину строк, чтобы получить эту функциональность с помощью списка. эта ссылка может дать четкое представление о ObservableCollection vs. List