if (listofelements.Contains(valueFieldValue.ToString()))
{
listofelements[listofelements.IndexOf(valueFieldValue.ToString())] = value.ToString();
}
위와 같이 교체했습니다. 이것보다 비교하는 다른 최선의 방법이 있습니까?
답변
Lambda를 사용하여 목록에서 인덱스를 찾고이 인덱스를 사용하여 목록 항목을 바꿉니다.
List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
listOfStrings[listOfStrings.FindIndex(ind=>ind.Equals("123"))] = "def";
답변
더 읽기 쉽고 효율적으로 만들 수 있습니다.
string oldValue = valueFieldValue.ToString();
string newValue = value.ToString();
int index = listofelements.IndexOf(oldValue);
if(index != -1)
listofelements[index] = newValue;
인덱스를 한 번만 요청합니다. 귀하의 접근 방식은 Contains
모든 항목을 반복 해야하는 (최악의 경우) 먼저 사용 IndexOf
하고 항목을 다시 열거하는 데 필요한 것을 사용 합니다.
답변
한 요소를 대체하기 위해 목록에 두 번 액세스하고 있습니다. 간단한 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);
}
}
}
참조 유형의 객체를 제자리에서 변경하기 위해 처음 두 가지 방법이 추가되었습니다. 물론 모든 유형에 대해 세 번째 방법 만 사용할 수 있습니다.
PS Mike의 관찰 덕분에 ReplaceAll 메서드를 추가했습니다.
답변
rokkuchan의 답변에 따라 약간의 업그레이드 :
List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
int index = listOfStrings.FindIndex(ind => ind.Equals("123"));
if (index > -1)
listOfStrings[index] = "def";
답변
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
답변
조건 자 조건을 기반으로하는 다음 확장을 사용할 수 있습니다.
/// <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;
}
참고 :-ThrowIfArgumentIsNull 확장 대신 다음과 같은 일반적인 접근 방식을 사용할 수 있습니다.
if (argName == null) throw new ArgumentNullException(nameof(argName));
따라서 이러한 확장을 사용하는 경우는 다음과 같이 해결할 수 있습니다.
string targetString = valueFieldValue.ToString();
listofelements.Replace(x => x.Equals(targetString), value.ToString());