Respostas:
Use Lambda para encontrar o índice na Lista e use este índice para substituir o item da lista.
List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
listOfStrings[listOfStrings.FindIndex(ind=>ind.Equals("123"))] = "def";
Equalsteste simples , o bom e velho IndexOffunciona tão bem e é mais conciso - como na resposta de Tim .
Você pode torná-lo mais legível e mais eficiente:
string oldValue = valueFieldValue.ToString();
string newValue = value.ToString();
int index = listofelements.IndexOf(oldValue);
if(index != -1)
listofelements[index] = newValue;
Isso pede apenas uma vez para o índice. Sua abordagem usa Containsprimeiro o que precisa fazer um loop de todos os itens (no pior caso), depois você usa o IndexOfque precisa enumerar os itens novamente.
Equalsou você só encontrará o objeto se for a mesma referência. Observe que stringtambém é um objeto (tipo de referência).
Equals e você também deve se lembrar que às vezes, ao mesmo tempo, você tem que implementarGetHashCode
GetHashCodese sobrescrever, Equalsmas GetHashCodesó é usado se o objeto estiver armazenado em um conjunto (fe Dictionaryou HashSet), então não é usado com IndexOfou Contains, apenas Equals.
IndexOfusa EqualityComparer<T>.Default. Você está dizendo que acabará chamando item.Equals(target)cada item da lista e, portanto, tem exatamente o mesmo comportamento da resposta de rokkuchan?
Você está acessando sua lista duas vezes para substituir um elemento. Acho que um forloop simples deve ser suficiente:
var key = valueFieldValue.ToString();
for (int i = 0; i < listofelements.Count; i++)
{
if (listofelements[i] == key)
{
listofelements[i] = value.ToString();
break;
}
}
Por que não usar os métodos de extensão?
Considere o seguinte código:
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}
O código-fonte:
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);
}
}
}
Os primeiros dois métodos foram adicionados para alterar os objetos de tipos de referência no local. Claro, você pode usar apenas o terceiro método para todos os tipos.
PS: Graças à observação de Mike , adicionei o método ReplaceAll.
Té um tipo de referência ou não é irrelevante. O que importa é se você deseja modificar (alterar) a lista ou retornar uma nova lista. O terceiro método é claro que não irá alterar a lista original, para que você não pode usar apenas o terceiro método ... . O primeiro método é aquele que responde à pergunta específica feita. Excelente código - apenas corrigindo sua descrição do que os métodos fazem :)
Use FindIndexe lambda para encontrar e substituir seus valores:
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
Você pode usar as próximas extensões que são baseadas em uma condição de predicado:
/// <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;
}
Observações: - Em vez da extensão ThrowIfArgumentIsNull, você pode usar uma abordagem geral como:
if (argName == null) throw new ArgumentNullException(nameof(argName));
Portanto, seu caso com essas extensões pode ser resolvido como:
string targetString = valueFieldValue.ToString();
listofelements.Replace(x => x.Equals(targetString), value.ToString());
Não sei se é melhor ou não, mas você também pode usar
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");
Ou, com base na sugestão de Rusian L., se o item que você está procurando puder estar na lista mais de uma vez:
[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);
}
eu acho o melhor para fazer rápido e simples
encontre seu item na lista
var d = Details.Where(x => x.ProductID == selectedProduct.ID).SingleOrDefault();fazer clone do atual
OrderDetail dd = d;Atualize seu clone
dd.Quantity++;encontrar índice na lista
int idx = Details.IndexOf(d);remova o item fundado em (1)
Details.Remove(d);inserir
if (idx > -1)
Details.Insert(idx, dd);
else
Details.Insert(Details.Count, dd);