if (listofelements.Contains(valueFieldValue.ToString()))
{
listofelements[listofelements.IndexOf(valueFieldValue.ToString())] = value.ToString();
}
Yukarıdaki gibi değiştirdim. Karşılaştırmanın bundan başka en iyi yolu var mı?
Yanıtlar:
Listedeki dizini bulmak için Lambda'yı kullanın ve liste öğesini değiştirmek için bu dizini kullanın.
List<string> listOfStrings = new List<string> {"abc", "123", "ghi"};
listOfStrings[listOfStrings.FindIndex(ind=>ind.Equals("123"))] = "def";
Equalstest için olsa da , iyi eski de IndexOfişe yarar ve daha özlüdür - Tim'in cevabında olduğu gibi .
Daha okunaklı ve daha verimli hale getirebilirsiniz:
string oldValue = valueFieldValue.ToString();
string newValue = value.ToString();
int index = listofelements.IndexOf(oldValue);
if(index != -1)
listofelements[index] = newValue;
Bu yalnızca bir kez dizini sorar. Yaklaşımınız Containsönce tüm öğeleri döngüye sokması gereken (en kötü durumda) kullanır, ardından IndexOföğeleri tekrar numaralandırmanız gerekenleri kullanıyorsunuz .
Equalsveya nesneyi yalnızca aynı referanssa bulursunuz. Bunun stringaynı zamanda bir nesne (başvuru türü) olduğunu unutmayın.
Equals ve bazen aynı zamanda uygulamak zorunda olduğunuzu da hatırlamalısınızGetHashCode
GetHashCodegeçersiz kılmak eğer Equalsancak GetHashCodenesne kümesi (fe saklanır yalnızca kullanılır Dictionaryveya HashSet) onunla alışkın değil bu yüzden, IndexOfya Containssadece Equals.
IndexOfKullanan belgelerde okudum EqualityComparer<T>.Default. Sonunda item.Equals(target)listedeki her bir maddeyi arayacağını mı söylüyorsunuz ve bu nedenle rokkuchan'ın cevabı ile aynı davranışa mı sahip?
Listenize bir öğeyi değiştirmek için iki kez erişiyorsunuz. Bence basit fordöngü yeterli olmalı:
var key = valueFieldValue.ToString();
for (int i = 0; i < listofelements.Count; i++)
{
if (listofelements[i] == key)
{
listofelements[i] = value.ToString();
break;
}
}
Neden uzantı yöntemlerini kullanmıyorsunuz?
Aşağıdaki kodu göz önünde bulundurun:
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}
Kaynak kodu:
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(nameof(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(nameof(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(nameof(source));
return source.Select(x => EqualityComparer<T>.Default.Equals(x, oldValue) ? newValue : x);
}
}
}
Referans türlerinin nesnelerini yerinde değiştirmek için ilk iki yöntem eklenmiştir. Tabii ki, tüm türler için sadece üçüncü yöntemi kullanabilirsiniz.
Not: Mike'ın gözlemi sayesinde ReplaceAll yöntemini ekledim.
Tbir referans türü olup olmadığı önemli değildir. Önemli olan, listeyi mutasyona uğratmak (değiştirmek) veya yeni bir liste döndürmek isteyip istemediğinizdir. Bunu elbette Üçüncü yöntem, orijinal listeyi değiştirmez olamaz sadece üçüncü yöntemi kullanın ... . İlk yöntem, sorulan belirli soruyu yanıtlayan yöntemdir. Mükemmel kod - sadece yöntemlerin ne işe yaradığına dair açıklamanızı düzeltir :)
FindIndexDeğerlerinizi bulmak ve değiştirmek için ve lambda kullanın :
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
Bir dayanak koşulu temel alan sonraki uzantıları kullanabilirsiniz:
/// <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;
}
Notlar: - ThrowIfArgumentIsNull uzantısı yerine, aşağıdaki gibi genel bir yaklaşım kullanabilirsiniz:
if (argName == null) throw new ArgumentNullException(nameof(argName));
Yani bu uzantılarla ilgili durumunuz şu şekilde çözülebilir:
string targetString = valueFieldValue.ToString();
listofelements.Replace(x => x.Equals(targetString), value.ToString());
En iyisi mi değil mi bilmiyorum ama sen de kullanabilirsin
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");
Veya, aradığınız öğe listede birden çok kez yer alabiliyorsa, Rusian L.'nin önerisine dayanarak:
[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);
}
hızlı ve basit yapmak için en iyisini buluyorum
öğeyi listede bul
var d = Details.Where(x => x.ProductID == selectedProduct.ID).SingleOrDefault();
akımdan klon yap
OrderDetail dd = d;
Klonunuzu güncelleyin
dd.Quantity++;
listede dizin bul
int idx = Details.IndexOf(d);
(1) içindeki bulunan öğeyi kaldır
Details.Remove(d);
eklemek
if (idx > -1)
Details.Insert(idx, dd);
else
Details.Insert(Details.Count, dd);