2012-08-08 16 views
48

Bir tablodan gelen bazı sütun değerlerinin bir listesini aldığımı söyler, boş dizeleri ve yinelenen değerleri nasıl kaldırabilirim.boş dizeleri listeden kaldırma, sonra da bir listeden yinelenen değerleri kaldırma

List<string> dtList = dtReportsList.AsEnumerable().Select(dr => dr.Field<string>("column1")).ToList(); 

Bu sadece şimdi kodlu da budur ama ama Amiram kodu yol daha şık, bu yüzden burada bu cevabı nasıl yaptığımı olduğunu seçecektir: Aşağıdaki kodu bakınız

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")); 


     } 
+0

RemoveAll() mutatlarının dtList; Kaldırılan her öğe, Listeyi, kullandığı temel dizideki daha yüksek dizinlerdeki öğeleri yeniden düzenlemeye zorlar. Amiram'ın Onun yöntemi ile yaptığı gibi onları atlamak daha hızlı olurdu. – KeithS

cevap

119
dtList = dtList.Where(s => !string.IsNullOrWhiteSpace(s)).Distinct().ToList() 

Boş dizgeyi kabul ettim ve boşluk boş gibi. değil IsNullOrEmpty (izin boşluk) veya s != null kullanabiliyorsa

+2

Bu çok güzel kodu beğendim – EaterOfCode

+0

Sadece bir şey; Distinct() ile ayrıştırma, yöntemin en kötü durumu alması gerektiğinden nispeten verimsizdir. – KeithS

+0

@KeithS Bu veriler hakkında “Distinct” ın optimize edilmesine izin vermediği iddiaları nelerdir? – Servy

7

Amiram cevabı uygulanan bir N operasyondur gibi) (doğru, ama Farklı olduğu; Listedeki her öğe için, algoritma onu zaten işlenmiş tüm öğelere karşılaştırır ve benzersizse veya döndürmezse onu döndürürse döndürür. Daha iyisini yapabiliriz. Çizelge, A A, sıralı bir zamanda çıkarılabilir; Geçerli eleman önceki öğeye eşitse, dikkate almayın, aksi halde döndürün. Sıralama NlogN Bu nedenle çok daha Koleksiyonu sıralamak zorunda, bazı parası almak: Bu, aynı elementleri döndürür

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(); 

; Sadece sıralanmışlar.

+0

Harika. Eğer yanılmıyorsam, öğeyi yineleyerek gerçekten siparişi gerçekleştiriyorsunuz. Metodunu "tembel" yapmanın bir yolunu düşünebilir misin? –

+0

Ne yazık ki, çoğu çeşit, sıralanacak tüm koleksiyon hakkında bilgi gerektirir; En son öğe, iade edilmesi gereken ilk şey olabilir. Bu nedenle, girdinin tüm öğeleri, çıktının ilk elemanını üretmek için değerlendirilmelidir. Bunun bir sonraki unsurunu bulduktan sonra kesintiye uğrayabileceğimiz tek şey bir SelectionSort varyantıdır ve bu durumda başladığımız yere geri dönüyoruz. – KeithS

+0

Ayrıca, bizim durumumuzda, tüm operasyonun sonucu ile başlamak için "istekli" yürütme gerektiren bir liste. Onunla IEnumerable olarak çalışmayı ve yürütmeyi ertelemek istiyorsak, işlevin etini alabilir ve IEnumerable'ı uygulayan gizli bir Iterator sınıfına koyabilirsiniz. – KeithS

1

Amiram Korach çözümü gerçekten düzenli. İşte çok yönlülük uğruna bir alternatif.

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(); 
+3

Bu işe yararken, Where cümlesi daha hızlıdır çünkü girdi koleksiyonunu değiştirmek zorunda kalmaz. Öğeleri listeden kaldırırken yapılması gereken "vardiyaların" sayısını en aza indiriyorsunuz, ancak girişten hiçbir şey çıkarmamak; Sadece eşleşmeyen öğelerin üzerinden atlar. – KeithS

+0

Açıklama için teşekkürler. – IneedHelp

İlgili konular