字符在字符串数组中出现的最大出现次数
在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();
您可以使用Linq
与Regex
结合使用:
myStrings.Select(x => Regex.Matches(x, "#").Count).max();