Powiedzmy, że mam listę niektórych wartości kolumn pochodzących z tabeli, jak usunąć puste ciągi i zduplikowane wartości. Zobacz poniższy kod:
List<string> dtList = dtReportsList.AsEnumerable().Select(dr => dr.Field<string>("column1")).ToList();
Właśnie to zakodowałem, ale kod Amirama jest o wiele bardziej elegancki, więc wybiorę odpowiedź tutaj, jak to zrobiłem:
DataTable dtReportsList = someclass.GetReportsList();
if (dtReportsList.Rows.Count > 0)
{
List<string> dtList = dtReportsList.AsEnumerable().Select(dr => dr.Field<string>("column1")).ToList();
dtList.RemoveAll(x=>x == "");
dtList = dtList.Distinct().ToList();
rcboModule.DataSource = dtList;
rcboModule.DataBind();
rcboModule.Items.Insert(0, new RadComboBoxItem("All", "All"));
}
Odpowiedzi:
dtList = dtList.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList()
Założyłem, że pusty łańcuch i białe znaki są jak null. Jeśli nie, możesz użyć
IsNullOrEmpty
(zezwalaj na białe znaki) lubs != null
źródło
Distinct
nie pozwalają na ich optymalizację?Odpowiedź Amirama jest poprawna, ale Distinct (), jak zaimplementowano, jest operacją N 2 ; dla każdego elementu na liście algorytm porównuje go ze wszystkimi już przetworzonymi elementami i zwraca go, jeśli jest unikalny, lub ignoruje go, jeśli nie. Możemy zrobić lepiej.
Posortowana lista może być deduped w czasie liniowym; jeśli bieżący element jest równy poprzedniemu, zignoruj go, w przeciwnym razie zwróć. Sortowanie to NlogN, więc nawet posortowanie kolekcji daje pewne korzyści:
public static IEnumerable<T> SortAndDedupe<T>(this IEnumerable<T> input) { var toDedupe = input.OrderBy(x=>x); T prev; foreach(var element in toDedupe) { if(element == prev) continue; yield return element; prev = element; } } //Usage dtList = dtList.Where(s => !string.IsNullOrWhitespace(s)).SortAndDedupe().ToList();
Zwraca te same elementy; są po prostu sortowane.
źródło
Distinct
używa haszowania i powinno być bliżej O (N) niż O (N ^ 2). źródłoRozwiązanie Amirama Koracha jest rzeczywiście uporządkowane. Oto alternatywa dla wszechstronności.
var count = dtList.Count; // Perform a reverse tracking. for (var i = count - 1; i > -1; i--) { if (dtList[i]==string.Empty) dtList.RemoveAt(i); } // Keep only the unique list items. dtList = dtList.Distinct().ToList();
źródło
Aby uprościć rozwiązanie Amirama Koracha :
dtList.RemoveAll(s => string.IsNullOrWhiteSpace(s))
Nie ma potrzeby używania Distinct () lub ToList ()
źródło