Antworten:
Verwenden Sie Lambda, um den Index in der Liste zu finden, und verwenden Sie diesen Index, um das Listenelement zu ersetzen.
List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
listOfStrings[listOfStrings.FindIndex(ind=>ind.Equals("123"))] = "def";
EqualsTest IndexOffunktioniert gutes altes genauso gut und ist prägnanter - wie in Tims Antwort .
Sie könnten es lesbarer und effizienter machen:
string oldValue = valueFieldValue.ToString();
string newValue = value.ToString();
int index = listofelements.IndexOf(oldValue);
if(index != -1)
listofelements[index] = newValue;
Dies fragt nur einmal nach dem Index. Ihr Ansatz verwendet Containszuerst, um alle Elemente zu schleifen (im schlimmsten Fall), und dann, IndexOfum die Elemente erneut aufzulisten.
Equalsoder Sie finden das Objekt nur, wenn es dieselbe Referenz ist. Beachten Sie, dass dies stringauch ein Objekt ist (Referenztyp).
Equals und Sie müssen sich auch daran erinnern, dass Sie manchmal gleichzeitig implementieren müssenGetHashCode
GetHashCodewenn Sie außer Kraft setzen , Equalssondern GetHashCodewird nur verwendet , wenn das Objekt in einem Satz (fe gespeichert ist Dictionaryoder HashSet), so ist es nicht mit verwendet IndexOfoder Containsnur Equals.
IndexOfverwenden EqualityComparer<T>.Default. Wollen Sie damit sagen, dass irgendwann item.Equals(target)jedes Element in der Liste aufgerufen wird und sich daher genauso verhält wie Rokkuchans Antwort?
Sie greifen zweimal auf Ihre Liste zu, um ein Element zu ersetzen. Ich denke, eine einfache forSchleife sollte ausreichen:
var key = valueFieldValue.ToString();
for (int i = 0; i < listofelements.Count; i++)
{
if (listofelements[i] == key)
{
listofelements[i] = value.ToString();
break;
}
}
Warum nicht die Erweiterungsmethoden verwenden?
Betrachten Sie den folgenden Code:
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}
Der Quellcode:
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);
}
}
}
Die ersten beiden Methoden wurden hinzugefügt, um die Objekte der Referenztypen zu ändern. Natürlich können Sie für alle Typen nur die dritte Methode verwenden.
PS Dank Mikes Beobachtung habe ich die ReplaceAll-Methode hinzugefügt.
Tes sich um einen Referenztyp handelt oder nicht, spielt keine Rolle. Entscheidend ist, ob Sie die Liste mutieren (ändern) oder eine neue Liste zurückgeben möchten. Die dritte Methode natürlich wird die ursprüngliche Liste nicht ändern, so dass Sie nicht können nur die dritte Methode verwenden ... . Die erste Methode beantwortet die spezifische Frage. Ausgezeichneter Code - korrigieren Sie einfach Ihre Beschreibung der Methoden :)
Verwenden Sie FindIndexund Lambda, um Ihre Werte zu finden und zu ersetzen:
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
Sie können die nächsten Erweiterungen verwenden, die auf einer Prädikatbedingung basieren:
/// <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;
}
Anmerkungen: - Anstelle der Erweiterung ThrowIfArgumentIsNull können Sie einen allgemeinen Ansatz wie den folgenden verwenden:
if (argName == null) throw new ArgumentNullException(nameof(argName));
Ihr Fall mit diesen Erweiterungen kann also wie folgt gelöst werden:
string targetString = valueFieldValue.ToString();
listofelements.Replace(x => x.Equals(targetString), value.ToString());
Ich weiß nicht, ob es am besten ist oder nicht, aber Sie können es auch verwenden
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");
Oder bauen Sie auf den Vorschlag von Rusian L. auf, wenn der gesuchte Artikel mehr als einmal in der Liste enthalten sein kann ::
[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);
}
Ich finde es am besten, es schnell und einfach zu machen
Finden Sie Ihren Artikel in der Liste
var d = Details.Where(x => x.ProductID == selectedProduct.ID).SingleOrDefault();Klon aus dem Strom machen
OrderDetail dd = d;Aktualisieren Sie Ihren Klon
dd.Quantity++;Index in Liste finden
int idx = Details.IndexOf(d);Gründungsgegenstand in (1) entfernen
Details.Remove(d);einfügen
if (idx > -1)
Details.Insert(idx, dd);
else
Details.Insert(Details.Count, dd);