C# 如何以最佳方式替换列表项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17188966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 08:47:33  来源:igfitidea点击:

How to replace list item in best way

c#

提问by Ragavan

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

I have replaced like above. Is there any other bestway to place compare than this one?

我已经像上面那样替换了。除了这个,还有其他最好的方法可以进行比较吗?

采纳答案by rokkuchan

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

使用 Lambda 在 List 中查找索引并使用该索引替换列表项。

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

回答by Tim Schmelter

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 Containsfirst which needs to loop all items(in the worst case), then you're using IndexOfwhich needs to enumerate the items again .

这仅询问一次索引。您的方法Contains首先使用which 需要循环所有项目(在最坏的情况下),然后您使用IndexOfwhich 需要再次枚举项目。

回答by gzaxx

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

您正在访问您的列表两次以替换一个元素。我认为简单的for循环应该足够了:

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

回答by Nik

I don't if it is best or not but you can use it also

我不知道它是否最好,但你也可以使用它

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

回答by Alex Jolig

Use FindIndexand lambda to find and replace your values:

使用FindIndex和 lambda 来查找和替换您的值:

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

回答by Ruslan L.

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 duplicate
  • There is no need to type long linq expressions
  • There is no need for additional usings
  • 没有代码重复
  • 无需键入长 linq 表达式
  • 无需额外使用

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

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.

PS 感谢Mike 的观察,我添加了 ReplaceAll 方法。

回答by mike

Or, building on Rusian L.'s suggestion, if the item you're searching for can be in the list more than once::

或者,根据 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);
}

回答by Fejs

Following rokkuchan's answer, just a little upgrade:

按照 rokkuchan 的回答,只需一点点升级:

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

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

回答by Tarrah Arshad

i find best for do it fast and simple

我发现最好的方法是快速而简单

  1. find ur item in list

    var d = Details.Where(x => x.ProductID == selectedProduct.ID).SingleOrDefault();
    
  2. make clone from current

    OrderDetail dd = d;
    
  3. Update ur clone

    dd.Quantity++;
    
  4. find index in list

    int idx = Details.IndexOf(d);
    
  5. remove founded item in (1)

      Details.Remove(d);
    
  6. insert

     if (idx > -1)
          Details.Insert(idx, dd);
      else
          Details.Insert(Details.Count, dd);
    
  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);
    

回答by Alexander Tolstikov

You can use the next extensions which are based on a predicate condition:

您可以使用基于谓词条件的下一个扩展:

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

Notes: - Instead of ThrowIfArgumentIsNull extension, you can use a general approach like:

注意: - 您可以使用一般方法代替 ThrowIfArgumentIsNull 扩展:

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

So your case with these extensions can be solved as:

因此,您使用这些扩展的情况可以解决为:

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