2010-08-12 12 views
6

Mam listę typu ciąg w projekcie .NET 3.5. Lista zawiera tysiące ciągów znaków, ale ze względu na zwięzłość powiemy, że ma po prostu 5 strun.Zapytanie o listę tylko dla duplikatów

List<string> lstStr = new List<string>() { 
      "Apple", "Banana", "Coconut", "Coconut", "Orange"}; 

Załóżmy, że lista jest posortowana (jak można powiedzieć powyżej). Potrzebuję kwerendy LINQ, która usunie wszystkie ciągi, które są duplikaty , a nie. W rezultacie otrzymam listę zawierającą tylko dwa ciągi "kokosowe".

Czy można to zrobić za pomocą zapytania LINQ? Jeśli tak nie jest, będę musiał uciec się do skomplikowanych pętli, co mogę zrobić, ale nie chciałem, chyba że musiałem.

Odpowiedz

4

tutaj jest kod do znajdowania duplikatów tworzą ciąg arrya

int[] listOfItems = new[] { 4, 2, 3, 1, 6, 4, 3 }; 
var duplicates = listOfItems 
    .GroupBy(i => i) 
    .Where(g => g.Count() > 1) 
    .Select(g => g.Key); 
foreach (var d in duplicates) 
    Console.WriteLine(d); 
4

var dupes = lstStr.Where(x => lstStr.Sum(y => y==x ? 1 : 0) > 1);

LUB

var dupes = lstStr.Where((x,i) => ( (i > 0 && x==lstStr[i-1]) 
            || (i < lstStr.Count-1 && x==lstStr[i+1])); 

Zauważ, że pierwszy z nich wymienia listę dla każdego elementu, który zabierze O (n²) czas (ale nie przejmie listę posortowaną). Drugi to O (n) (i zakłada posortowaną listę).

0
var temp = new List<string>(); 

foreach(var item in list) 
{ 
    var stuff = (from m in list 
       where m == item 
       select m); 
    if (stuff.Count() > 1) 
    { 
     temp = temp.Concat(stuff); 
    } 
} 
1

To powinno zadziałać, i jest O (N) raczej niż O (N^2) innych odpowiedzi. (Uwaga, to wykorzystuje fakt, że lista jest posortowana, więc tak naprawdę jest wymagana).

IEnumerable<T> OnlyDups<T>(this IEnumerable<T> coll) 
    where T: IComparable<T> 
{ 
    IEnumerator<T> iter = coll.GetEnumerator(); 
    if (iter.MoveNext()) 
    { 
     T last = iter.Current; 
     while(iter.MoveNext()) 
     { 
      if (iter.Current.CompareTo(last) == 0) 
      { 
        yield return last; 
        do 
        { 
         yield return iter.Current; 
        } 
        while(iter.MoveNext() && iter.Current.CompareTo(last) == 0); 
      } 
      last = iter.Current; 
     } 
} 

używać go tak:

IEnumerable<string> onlyDups = lstStr.OnlyDups(); 

lub

List<string> onlyDups = lstStr.OnlyDups().ToList(); 
+0

nie używać LINQ? – McKay

+0

@McKay: Tak, ale OP stwierdził, że można założyć, że lista jest posortowana. –

+0

@McKey (poprawione pytanie): technicznie nie, ale zachowuje interfejs w stylu linq i może być używany jako część większej instrukcji LINQ. –

Powiązane problemy