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

Rag*_*van 81 c#

if (listofelements.Contains(valueFieldValue.ToString()))
{
    listofelements[listofelements.IndexOf(valueFieldValue.ToString())] = value.ToString();
}
Run Code Online (Sandbox Code Playgroud)

我已经取代了上面的内容.除此之外还有其他比较优势吗?

Tim*_*ter 101

您可以使其更具可读性和效率:

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

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

  • 这是查找文字的正确答案 - 整数、字符串,但不太适合查找对象。但是,我更喜欢 rokkuchan 的答案,因为它是通用的。 (2认同)

小智 77

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

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

  • 检查-1!Incase项目不在集合中 (9认同)
  • 加一个使用FindIndex (3认同)
  • 这是最好的通用答案恕我直言,因为它也可以用于比较对象。 (2认同)

gza*_*axx 15

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

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

  • @Pap抱歉,我不够清楚.他正在迭代他的列表两次(首先检查项目是否在列表中,第二项是获取项目索引). (4认同)

小智 11

为什么不使用扩展方法?

请考虑以下代码:

        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}
Run Code Online (Sandbox Code Playgroud)
  • 没有代码重复
  • 无需键入long 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

添加了前两个方法来更改引用类型的对象.当然,您只能对所有类型使用第三种方法.

PS感谢mike的观察,我添加了ReplaceAll方法.


Ale*_*kov 6

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

    /// <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;
    }
Run Code Online (Sandbox Code Playgroud)

注意: - 您可以使用如下通用方法,而不是 ThrowIfArgumentIsNull 扩展:

if (argName == null) throw new ArgumentNullException(nameof(argName));
Run Code Online (Sandbox Code Playgroud)

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

string targetString = valueFieldValue.ToString();
listofelements.Replace(x => x.Equals(targetString), value.ToString());
Run Code Online (Sandbox Code Playgroud)


Ale*_*lig 5

使用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
Run Code Online (Sandbox Code Playgroud)


Fej*_*ejs 5

按照rokkuchan的回答,只需稍作升级:

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

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