字符在字符串数组中出现的最大次数
Maximum number of occurrences a character appears in an array of strings
在 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();
}
然而有一个很大的HOWEVER。在 C# 中,您所说的 char
不是您在您的语言中所说的字符。这在其他帖子中已被广泛讨论,例如:Fastest way to split a huge text into smaller chunks and How can I perform a Unicode aware character by character comparison? 那么我不会在这里重复所有内容。要成为 "Unicode aware" 你需要让你的代码更复杂(请注意这里写的代码是未经测试的):
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()
)。在这种情况下不要武断地决定要做什么(如果应该发生则抛出异常或只是return 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();
在 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();
}
然而有一个很大的HOWEVER。在 C# 中,您所说的 char
不是您在您的语言中所说的字符。这在其他帖子中已被广泛讨论,例如:Fastest way to split a huge text into smaller chunks and How can I perform a Unicode aware character by character comparison? 那么我不会在这里重复所有内容。要成为 "Unicode aware" 你需要让你的代码更复杂(请注意这里写的代码是未经测试的):
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()
)。在这种情况下不要武断地决定要做什么(如果应该发生则抛出异常或只是return 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();