if (listofelements.Contains(valueFieldValue.ToString()))
{
listofelements[listofelements.IndexOf(valueFieldValue.ToString())] = value.ToString();
}
He reemplazado como arriba. ¿Hay alguna otra mejor manera de comparar el lugar que esta?
Respuestas:
Use Lambda para buscar el índice en la Lista y use este índice para reemplazar el elemento de la lista.
List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
listOfStrings[listOfStrings.FindIndex(ind=>ind.Equals("123"))] = "def";
Equalsprueba simple , el buen viejo IndexOffunciona igual de bien y es más conciso, como en la respuesta de Tim .
Podría hacerlo más legible y más eficiente:
string oldValue = valueFieldValue.ToString();
string newValue = value.ToString();
int index = listofelements.IndexOf(oldValue);
if(index != -1)
listofelements[index] = newValue;
Esto solicita solo una vez el índice. Su enfoque usa Containsprimero el que necesita repetir todos los elementos (en el peor de los casos), luego está usando el IndexOfque necesita enumerar los elementos nuevamente.
Equalso solo encontrará el objeto si es la misma referencia. Tenga en cuenta que stringtambién es un objeto (tipo de referencia).
Equals y también debe recordar que a veces al mismo tiempo tiene que implementarGetHashCode
GetHashCodesi anula, Equalspero GetHashCodesolo se usa si el objeto está almacenado en un conjunto (fe Dictionaryo HashSet), por lo que no se usa con IndexOfo Contains, solo Equals.
IndexOfusa EqualityComparer<T>.Default. ¿Estás diciendo que eventualmente llamará item.Equals(target)a cada elemento de la lista y, por lo tanto, tiene exactamente el mismo comportamiento que la respuesta de rokkuchan?
Estás accediendo a tu lista dos veces para reemplazar un elemento. Creo que un forbucle simple debería ser suficiente:
var key = valueFieldValue.ToString();
for (int i = 0; i < listofelements.Count; i++)
{
if (listofelements[i] == key)
{
listofelements[i] = value.ToString();
break;
}
}
¿Por qué no utilizar los métodos de extensión?
Considere el siguiente 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}
El código fuente:
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);
}
}
}
Se han agregado los dos primeros métodos para cambiar los objetos de los tipos de referencia en su lugar. Por supuesto, puede usar solo el tercer método para todos los tipos.
PD Gracias a la observación de Mike , agregué el método ReplaceAll.
Tes un tipo de referencia o no es irrelevante. Lo que importa es si desea mutar (alterar) la lista o devolver una nueva lista. El tercer método, por supuesto, no alterará la lista original, por lo que no se puede utilizar sólo el tercer método ... . El primer método es el que responde a la pregunta específica formulada. Excelente código: simplemente corrige su descripción de lo que hacen los métodos :)
Utilice FindIndexy lambda para buscar y reemplazar sus 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
Puede usar las siguientes extensiones que se basan en una condición 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;
}
Notas: - En lugar de la extensión ThrowIfArgumentIsNull, puede utilizar un enfoque general como:
if (argName == null) throw new ArgumentNullException(nameof(argName));
Entonces su caso con estas extensiones se puede resolver como:
string targetString = valueFieldValue.ToString();
listofelements.Replace(x => x.Equals(targetString), value.ToString());
No sé si es mejor o no, pero también puedes usarlo.
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");
O, basándose en la sugerencia de Rusian L., si el artículo que está buscando puede estar en la lista más de una 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);
}
Puede usar una expresión lambda como esta.
int index = listOfElements.FindIndex(item => item.Id == id);
if (index != -1)
{
listOfElements[index] = newValue;
}
encuentro lo mejor para hacerlo rápido y simple
encuentra tu artículo en la lista
var d = Details.Where(x => x.ProductID == selectedProduct.ID).SingleOrDefault();hacer un clon de la corriente
OrderDetail dd = d;Actualizar tu clon
dd.Quantity++;buscar índice en la lista
int idx = Details.IndexOf(d);eliminar artículo fundado en (1)
Details.Remove(d);insertar
if (idx > -1)
Details.Insert(idx, dd);
else
Details.Insert(Details.Count, dd);