2010-08-12 66 views
6

我有一个.NET 3.5项目中的字符串类型列表。该列表中有数千个字符串,但为了简洁起见,我们将说它只有5个字符串。查询仅重复列表

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

假设列表已排序(如上所述)。我需要的是一个LINQ查询,它将删除所有而不是重复的字符串。所以结果会给我一个只包含两个“椰子”字符串的列表。

这可能与一个LINQ查询?如果不是,那么我将不得不求助于一些复杂的循环,我可以这样做,但除非必须,否则我不想。

回答

4

这里寻找重复的代码格式的字符串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);

OR

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

注意,第一个枚举列表,每一个这需要O(N²)时间(但不承担排序列表)元素。第二个是O(n)(并且假定有排序的列表)。

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

这应该工作,并且是O(N)而不是其他答案的O(N^2)。 (注意,这确实使用了列表排序的事实,所以这确实是一个要求)。

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; 
     } 
} 

使用这样的:

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

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

这不使用LINQ? – McKay 2010-08-12 18:35:18

+0

@McKay:是的,但OP表示可以假定列表已排序。 – 2010-08-12 18:36:26

+0

@McKey(修改后的问题):技术上没有,但它确实保留了一个linq样式的接口,并且可以用作更大的LINQ语句的一部分。 – 2010-08-12 18:44:29