字符在字符串数组中出现的最大出现次数
本文关键字:数组 字符 字符串 | 更新日期: 2023-09-27 18:32:24
在 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[]
数组的更简单方法吗?
这可以变成一种可以在任何IEnumerable<string>
上工作的扩展方法吗?
首先,让我们将字符串投影到一个包含匹配计数的序列中:
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<string> strings, char ch)
{
return strings
.Select(s => s.Count(c => c == ch))
.Max();
}
然而,有一个很大的然而。在 C# 中,你所说的char
不是你语言中所说的字符。这在其他帖子中已经广泛讨论,例如:将大文本拆分为较小块的最快方法和如何逐字符比较执行 Unicode 感知字符?那我就不在这里重复了。要"了解 Unicode",您需要使您的代码更加复杂(请注意,代码是写在这里的,然后未经测试):
private static IEnumerable<string> EnumerateCharacters(string s)
{
var enumerator = StringInfo.GetTextElementEnumerator(s.Normalize());
while (enumerator.MoveNext())
yield return (string)enumerator.Value;
}
然后将我们的原始代码更改为:
public static int CountMaximumOccurrencesOf(this IEnumerable<string> strings, string character)
{
return strings
.Select(s => s.EnumerateCharacters().Count(c => String.Equals(c, character, StringComparison.CurrentCulture))
.Max();
}
请注意,仅Max()
要求集合不为空(如果集合可能为空并且不是错误,请使用DefaultIfEmpty()
)。为了不随意决定在这种情况下要做什么(如果应该发生或只返回 0),您可以降低此方法的专业化程度,并将此责任留给调用方:
public static int CountOccurrencesOf(this IEnumerable<string> 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
为空时不抛出异常,而是恢复为 0
。
var maximum = myStrings.Select(e => e.Count(ee => ee == '#')).DefaultIfEmpty().Max();
你可以将Linq
组合到Regex
myStrings.Select(x => Regex.Matches(x, "#").Count).max();