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

C# 如何以最佳方式替换列表项,c#,C#,我已经像上面那样更换了。除了这一种,还有其他最好的放置比较的方法吗?您可以让它更可读、更高效: if (listofelements.Contains(valueFieldValue.ToString())) { listofelements[listofelements.IndexOf(valueFieldValue.ToString())] = value.ToString(); } 这只需要一次索引。您的方法首先使用Contains,它需要循环所有项目(在最坏的情况下),然后使用

我已经像上面那样更换了。除了这一种,还有其他最好的放置比较的方法吗?

您可以让它更可读、更高效:

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

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

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

string oldValue = valueFieldValue.ToString();
string newValue = value.ToString();
int index = listofelements.IndexOf(oldValue);
if(index != -1)
    listofelements[index] = newValue;
var key=valueFieldValue.ToString();
for(int i=0;i
我不知道它是否最好,但你也可以使用它

var key = valueFieldValue.ToString();
for (int i = 0; i < listofelements.Count; i++)
{
    if (listofelements[i] == key)
    {
        listofelements[i] = value.ToString();
        break;
    }
}
列表数据=新列表
(新字符串[]{“计算机”、“A”、“B”、“计算机”、“B”、“A”});
int[]index=Enumerable.Range(0,data.Count)。其中
(i=>data[i]==“计算机”).ToArray();
ForEach(索引,i=>data[i]=“Calculator”);

使用Lambda查找列表中的索引,并使用此索引替换列表项

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");
List listofstring=新列表{“abc”、“123”、“ghi”};
listOfStrings[listOfStrings.FindIndex(ind=>ind.Equals(“123”))]=“def”;

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

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

为什么不使用扩展方法呢

考虑以下代码:

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
var intArray=newint[]{0,1,1,2,3,4};
//替换第一个实例并返回索引
var指数=intArray.Replace(1,0);
// {0, 0, 1, 2, 3, 4}; 索引=1
var stringList=新列表{“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表达式
  • 不需要额外使用
源代码:

        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
{
公共静态类扩展
{
公共静态int Replace(此IList源、T oldValue、T newValue)
{
if(source==null)
抛出新ArgumentNullException(nameof(source));
var index=source.IndexOf(旧值);
如果(索引!=-1)
来源[索引]=新值;
收益指数;
}
公共静态void ReplaceAll(此IList源、T oldValue、T newValue)
{
if(source==null)
抛出新ArgumentNullException(nameof(source));
int指数=-1;
做
{
索引=source.IndexOf(oldValue);
如果(索引!=-1)
来源[索引]=新值;
}而(索引!=-1);
}
公共静态IEnumerable替换(此IEnumerable源、T oldValue、T newValue)
{
if(source==null)
抛出新ArgumentNullException(nameof(source));
返回source.Select(x=>EqualityComparer.Default.Equals(x,oldValue)?newValue:x);
}
}
}
添加了前两个方法以就地更改引用类型的对象。当然,您可以对所有类型使用第三种方法


另外,由于,我添加了ReplaceAll方法。

或者,根据Rusian L.的建议,如果您要搜索的项目可以多次出现在列表中:

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);
        }
    }
}
[Extension()]
公共void ReplaceAll(列表输入、T搜索、T替换)
{
int i=0;
做{
i=input.FindIndex(i,s=>EqualityComparer.Default.Equals(s,search));
如果(i>-1){
输入(i)=替换;
继续;
}
打破
}虽然(正确);
}

按照rokkuchan的回答,只需稍微升级一下:

[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 listofstring=新列表{“abc”、“123”、“ghi”};
int index=listOfStrings.FindIndex(ind=>ind.Equals(“123”);
如果(索引>-1)
listOfStrings[index]=“def”;

我认为最适合快速、简单地完成它

  • 在列表中查找您的项目

    List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
    
    int index = listOfStrings.FindIndex(ind => ind.Equals("123"));
    if (index > -1)
        listOfStrings[index] =  "def";
    
  • 从当前复制

    var d = Details.Where(x => x.ProductID == selectedProduct.ID).SingleOrDefault();
    
  • 更新你的克隆

    OrderDetail dd = d;
    
  • 在列表中查找索引

    dd.Quantity++;
    
  • 删除(1)中的项目

  • 插入

      Details.Remove(d);
    

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

     if (idx > -1)
          Details.Insert(idx, dd);
      else
          Details.Insert(Details.Count, dd);
    
    因此,您的这些扩展案例可以通过以下方式解决:

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

    可以像这样使用lambda表达式

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

    @gzaxx。“您正在访问列表两次以替换一个元素。我认为简单for循环应该足够了。”。您在for-loop-mate中访问了多少次该列表?@Pap对不起,我说得不够清楚。他迭代他的列表两次(第一次是检查项目是否在列表中,第二次是获取项目索引)!如果该项目不在collectionsplus中,请使用FindIndex。这是IMHO的最佳通用答案,因为它也可用于比较对象。请参阅。虽然对于一个简单的
    Equals
    测试,良好的旧
    IndexOf
    也同样有效,并且更简洁-如中所示。这是查找文本(整数、字符串)的正确答案,但对于查找对象不是很好。但是,我更喜欢rokkuchan的答案,因为它是通用的。@SimchaKhabinsky:也适用于引用类型,该类型只需要覆盖
    等于
    ,否则只有当对象是相同的引用时,才能找到它。请注意,
    string
    也是一个对象(引用类型)。是的,您是对的。然而,我看到许多开发人员忘记了实现
    Equals
    ,您还必须记住,有时您必须同时实现
    GetHashCode
    @SimchaKhabinsky:是的,如果您覆盖
    Equals
    ,您应该始终覆盖
    GetHashCode
    ,但是
    GetHashCodeif (argName == null) throw new ArgumentNullException(nameof(argName));
    
    string targetString = valueFieldValue.ToString();
    listofelements.Replace(x => x.Equals(targetString), value.ToString());
    
    int index = listOfElements.FindIndex(item => item.Id == id);  
    if (index != -1) 
    {
        listOfElements[index] = newValue;
    }