字符在字符串数组中出现的最大出现次数

在C#中,给定数组:

string[] myStrings = new string[] { "test#test", "##test", "######", // Winner (outputs 6) }; 

如何找到字符#出现在单个字符串中的最大出现次数?

我目前的解决方案是:

 int maxOccurrences = 0; foreach (var myString in myStrings) { var occurrences = myString.Count(x => x == '#'); if (occurrences > maxOccurrences) { maxOccurrences = occurrences; } } return maxOccurrences; 

使用linq可以直接在myStrings[]数组上进行myStrings[]吗?

这可以成为一个可以在任何IEnumerable上工作的扩展方法吗?

首先让我们将你的字符串投射到一个匹配计数的序列中:

 myStrings.Select(x => x.Count(x => x == '#')) // {1, 2, 6} in your example 

然后选择最大值:

 int maximum = myStrings .Select(s => s.Count(x => x == '#')) .Max(); // 6 in your example 

让我们做一个扩展方法:

 public static int CountMaximumOccurrencesOf(this IEnumerable strings, char ch) { return strings .Select(s => s.Count(c => c == ch)) .Max(); } 

然而,有一个很大的问题。 你在C#中调用char的不是你用你的语言称为字符的东西。 这在其他post中已被广泛讨论,例如: 将大文本拆分成较小块的最快方法以及如何通过字符比较执行Unicode识别字符? 那么我不会在这里重复一切。 为了“识别Unicode”,你需要使你的代码更复杂(请注意代码在这里写,然后它是未经测试的):

 private static IEnumerable EnumerateCharacters(string s) { var enumerator = StringInfo.GetTextElementEnumerator(s.Normalize()); while (enumerator.MoveNext()) yield return (string)enumerator.Value; } 

然后将我们的原始代码更改为:

 public static int CountMaximumOccurrencesOf(this IEnumerable strings, string character) { return strings .Select(s => s.EnumerateCharacters().Count(c => String.Equals(c, character, StringComparison.CurrentCulture)) .Max(); } 

请注意, Max()单独要求集合不为空(如果集合可能为空并且不是错误,则使用DefaultIfEmpty() )。 要在这种情况下不要随意决定做什么(如果应该发生exception或只返回0则抛出exception),你可以使这种方法不那么专业化并将这个责任留给调用者:

 public static int CountOccurrencesOf(this IEnumerable strings, string character, StringComparison comparison = StringComparison.CurrentCulture) { Debug.Assert(character.EnumerateCharacters().Count() == 1); return strings .Select(s => s.EnumerateCharacters().Count(c => String.Equals(c, character, comparison )); } 

像这样使用:

 var maximum = myStrings.CountOccurrencesOf("#").Max(); 

如果您需要它不区分大小写:

 var maximum = myStrings.CountOccurrencesOf("à", StringComparison.CurrentCultureIgnoreCase) .Max(); 

您现在可以想象这种比较不仅限于某些深奥的语言,但它也适用于不变文化(en-US),然后对于必须始终与不变文化进行比较的字符串,您应该指定StringComparison.InvariantCulture 。 不要忘记您可能还需要为输入字符调用String.Normalize()

你可以写这样的东西。 注意DefaultIfEmpty的用法,如果myStrings为空,则不会抛出exception,但会恢复为0

 var maximum = myStrings.Select(e => e.Count(ee => ee == '#')).DefaultIfEmpty().Max(); 

您可以使用LinqRegex结合使用:

 myStrings.Select(x => Regex.Matches(x, "#").Count).max();