2011-09-06 89 views
1

我有一个字符串数组f.e.确定字符串数组中是否出现多次(C#)

string [] letters = { "a", "a", "b", "c" }; 

我需要找到一种方法来确定数组中的任何字符串是否出现多次。 我认为最好的办法是让一个新的字符串数组没有问题的字符串,并使用包含,

foreach (string letter in letters) 
{ 
    string [] otherLetters = //? 
    if (otherLetters.Contains(letter)) 
    { 
     //etc.  
    } 
} 

,但我无法弄清楚如何。 如果有人有解决这个或更好的方法,请回答。

回答

10

最简单的方法是使用GroupBy

var lettersWithMultipleOccurences = letters.GroupBy(x => x) 
              .Where(g => g.Count() > 1) 
              .Select(g => g.Key); 

这将第一组使用字母键的排列。然后它仅返回具有多个条目的组,并返回这些组的键。因此,您将有一个IEnumerable<string>,其中包含原始数组中出现多次的所有字母。在你的例子中,这只是“a”。

当心:由于LINQ使用延迟执行,列举lettersWithMultipleOccurences多次实施,将执行分组和过滤多次。为了避免这种情况,请拨打ToList()的结果:

var lettersWithMultipleOccurences = letters.GroupBy(x => x) 
              .Where(g => g.Count() > 1) 
              .Select(g => g.Key). 
              .ToList(); 

lettersWithMultipleOccurences现在将List<string>类型。

1

创建数组中的一个HashSet,并比较它们的大小:

var set = new HashSet(letters); 
bool hasDoubleLetters = set.Size == letters.Length; 
4

您可以在LINQ扩展方法:

if (letters.Distinct().Count() == letters.Count()) { 
    // no duplicates 
} 

Enumerable.Distinct删除重复。因此,letters.Distinct()将在您的示例中返回三个元素。

+1

点点更有效的办法是使用数组('letters.Length'),无需扩展的'.Length'财产 - 但肯定这是最优雅和高效的方式。 –

+0

@Shadow:好点。但是,出于美学原因,我将它放在'Count()'上,因为在左侧使用'Count()'而在右侧使用'Length'看起来很奇怪。 – Heinzi

+0

这并不重要。 'Enumerable.Count()'使用'Count'属性,如果输入是'ICollection'或'ICollection'并且.NET数组都是。 –

1

一个HashSet会给你不错的表现:

HashSet<string> hs = new HashSet<string>(); 
foreach (string letter in letters) 
{ 
    if (hs.Contains(letter)) 
    { 
     //etc. more as once  
    } 
    else 
    { 
      hs.Add(letter); 
    } 
} 
+0

这大约比我的代码长五倍,不一定更高效。 –

+0

这取决于初始数组的填充和大小。 – Peter

相关问题