Risposte:
Utilizza Lambda per trovare l'indice nell'elenco e utilizza questo indice per sostituire l'elemento dell'elenco.
List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
listOfStrings[listOfStrings.FindIndex(ind=>ind.Equals("123"))] = "def";
Equalstest, il buon vecchio IndexOffunziona altrettanto bene ed è più conciso, come nella risposta di Tim .
Potresti renderlo più leggibile ed efficiente:
string oldValue = valueFieldValue.ToString();
string newValue = value.ToString();
int index = listofelements.IndexOf(oldValue);
if(index != -1)
listofelements[index] = newValue;
Questo richiede solo una volta per l'indice. Il tuo approccio utilizza Containsprima che deve eseguire il ciclo di tutti gli elementi (nel caso peggiore), quindi stai utilizzando IndexOfquale deve enumerare nuovamente gli elementi.
Equalso troverai l'oggetto solo se è lo stesso riferimento. Nota che stringè anche un oggetto (tipo di riferimento).
Equals e devi anche ricordare che a volte allo stesso tempo devi implementareGetHashCode
GetHashCodese si ignora Equals, ma GetHashCodeviene utilizzato solo se l'oggetto è memorizzato in un set (fe Dictionaryo HashSet), quindi non è usato con IndexOfo Contains, solo Equals.
IndexOfutilizza EqualityComparer<T>.Default. Stai dicendo che alla fine chiamerà item.Equals(target)ogni elemento nell'elenco, e quindi ha lo stesso identico comportamento della risposta di rokkuchan?
Stai accedendo al tuo elenco due volte per sostituire un elemento. Penso che un semplice forciclo dovrebbe essere sufficiente:
var key = valueFieldValue.ToString();
for (int i = 0; i < listofelements.Count; i++)
{
if (listofelements[i] == key)
{
listofelements[i] = value.ToString();
break;
}
}
Perché non utilizzare i metodi di estensione?
Considera il codice seguente:
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}
Il codice sorgente:
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);
}
}
}
I primi due metodi sono stati aggiunti per modificare gli oggetti dei tipi di riferimento in posizione. Ovviamente puoi usare solo il terzo metodo per tutti i tipi.
PS Grazie all'osservazione di Mike , ho aggiunto il metodo ReplaceAll.
Tè un tipo di riferimento o meno è irrilevante. Ciò che conta è se si desidera modificare (alterare) l'elenco o restituire un nuovo elenco. Il terzo metodo, naturalmente, non altera la lista originale, in modo da non si può utilizzare solo il terzo metodo ... . Il primo metodo è quello che risponde alla domanda specifica posta. Codice eccellente - correggo solo la descrizione di ciò che fanno i metodi :)
Usa FindIndexe lambda per trovare e sostituire i tuoi valori:
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
Puoi utilizzare le prossime estensioni basate su una condizione del predicato:
/// <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;
}
Note: - Invece dell'estensione ThrowIfArgumentIsNull, puoi utilizzare un approccio generale come:
if (argName == null) throw new ArgumentNullException(nameof(argName));
Quindi il tuo caso con queste estensioni può essere risolto come:
string targetString = valueFieldValue.ToString();
listofelements.Replace(x => x.Equals(targetString), value.ToString());
Non so se è meglio o no, ma puoi anche 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");
Oppure, basandosi sul suggerimento di Rusian L., se l'elemento che stai cercando può essere nell'elenco più di una volta:
[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);
}
trovo il modo migliore per farlo in modo semplice e veloce
trova il tuo articolo nell'elenco
var d = Details.Where(x => x.ProductID == selectedProduct.ID).SingleOrDefault();fare clone da corrente
OrderDetail dd = d;Aggiorna il tuo clone
dd.Quantity++;trova indice nell'elenco
int idx = Details.IndexOf(d);rimuovere l'elemento trovato in (1)
Details.Remove(d);inserire
if (idx > -1)
Details.Insert(idx, dd);
else
Details.Insert(Details.Count, dd);