myString.Length; //will get you your result
myString.Count(char.IsLetter); //if you only want the count of letters:
如何获取唯一字符计数?我的意思是对于“blabla”,结果必须为3,对于“998769”,结果将为4。是否有现成的函数可用?有什么建议吗?
var count = myString.Distinct().Count();
它利用了一个事实,即 string
实现了 IEnumerable<char>
。
没有 LINQ,你可以使用 HashSet<char>
做出与 Distinct
内部相同的操作:
var count = (new HashSet<char>(myString)).Count;
myString.Distinct().Count()
我在这里不会严格定义术语,因此请参考www.unicode.org。如果您想进行更广泛的讨论,请阅读如何执行基于Unicode的逐字符比较?,编码不是您必须考虑的唯一问题。
1)它没有考虑到.NET System.Char
不表示一个字符(或更具体地说是字形),而是UTF-16编码文本的代码单元(例如,使用表意文字)。通常它们是相同的,但不总是。
2) 如果您正在计算用户认为(或感知)的字符,则此方法将失败,因为它不检查组合字符,例如ا́(阿拉伯语中有许多这样的例子)。由于历史原因,存在重复项:例如é既是单个Unicode代码点,也是一个组合(那么该代码将失败)。
3) 我们谈论的是西方/美国对字符的定义。如果您正在为最终用户计算字符,则可能需要更改其期望的定义(例如,在韩语字符定义中可能不太明显,另一个例子是捷克文本ch始终被视为单个字符)。最后,请不要忘记在将字符转换为大写/小写时出现一些奇怪的事情(例如,在德语中,ß在大写时为SS,另请参见此帖子)。
C#字符串采用UTF-16编码(char
为两个字节),但UTF-16不是固定大小的编码方式,char
应该被正确地称为代码单元。这意味着什么?你可能有一个string
,它的Length
是2,但实际上用户将看到(并且实际上也是)只有一个字符(然后计数应该是1)。
如果你需要正确处理这个问题,那么你必须使事情变得更加复杂(和缓慢)。幸运的是,Char
类有一些有用的方法来处理代理项。
下面的代码未经测试(仅用于说明目的,因此绝对不是最优化的,我相信可以比这做得更好),所以只是作为进一步研究的起点:
int CountCharacters(string text)
{
HashSet<string> characters = new HashSet<string>();
string currentCharacter = "";
for (int i = 0; i < text.Length; ++i)
{
if (Char.IsHighSurrogate(text, i))
{
// Do not count this, next one will give the full pair
currentCharacter = text[i].ToString();
continue;
}
else if (Char.IsLowSurrogate(text, i))
{
// Our "character" is encoded as previous one plus this one
currentCharacter += text[i];
}
else
currentCharacter = text[i].ToString();
if (!characters.Contains(currentCharacter))
characters.Add(currentCharacter);
}
return characters.Count;
}
如果您必须处理组合字符(当然还包括编码),那么最好的方法是使用StringInfo类。您将枚举(然后计数)组合和编码字符:
StringInfo.GetTextElementEnumerator(text).Walk()
.Distinct().Count();
Walk()
是一个易于实现的扩展方法,它简单地遍历所有IEnumerator
元素(我们需要它,因为GetTextElementEnumerator()
返回的是IEnumerator
而不是IEnumerable
)。char
,而是一系列char
(为了简单起见,在这里作为string
本身返回)。再次强调,此代码不处理重复项。
abstract class Unicode
{
public static string CountCharacters(string text)
{
return GetConcreteClass().CountCharactersCore(text);
}
protected virtual string CountCharactersCore(string text)
{
// Default implementation, overridden in derived classes if needed
return StringInfo.GetTextElementEnumerator(text).Cast<string>()
.Distinct().Count();
}
private Dictionary<string, Unicode> _implementations;
private Unicode GetConcreteClass()
{
string cultureName = Thread.Current.CurrentCulture.Name;
// Check if concrete class has been loaded and put in dictionary
...
return _implementations[cultureName];
}
}
"blabla".Distinct().Count()
将会做到。
Distinct()
而不是Disctinct()
。 - DGibbs