我试图转换一些字符串,在法国加拿大,基本上,我想能够拿出法国重音标记在字母,同时保持字母。(例如,将é转换为e,那么crème brûlée就会变成creme brulee)
实现这一目标的最佳方法是什么?
我试图转换一些字符串,在法国加拿大,基本上,我想能够拿出法国重音标记在字母,同时保持字母。(例如,将é转换为e,那么crème brûlée就会变成creme brulee)
实现这一目标的最佳方法是什么?
当前回答
你可以从MMLib中使用字符串扩展。扩展nuget包:
using MMLib.RapidPrototyping.Generators;
public void ExtensionsExample()
{
string target = "aácčeéií";
Assert.AreEqual("aacceeii", target.RemoveDiacritics());
}
Nuget页面:https://www.nuget.org/packages/MMLib.Extensions/ Codeplex项目网站https://mmlib.codeplex.com/
其他回答
如果有人感兴趣,我正在寻找类似的东西,最后写了如下:
public static string NormalizeStringForUrl(string name)
{
String normalizedString = name.Normalize(NormalizationForm.FormD);
StringBuilder stringBuilder = new StringBuilder();
foreach (char c in normalizedString)
{
switch (CharUnicodeInfo.GetUnicodeCategory(c))
{
case UnicodeCategory.LowercaseLetter:
case UnicodeCategory.UppercaseLetter:
case UnicodeCategory.DecimalDigitNumber:
stringBuilder.Append(c);
break;
case UnicodeCategory.SpaceSeparator:
case UnicodeCategory.ConnectorPunctuation:
case UnicodeCategory.DashPunctuation:
stringBuilder.Append('_');
break;
}
}
string result = stringBuilder.ToString();
return String.Join("_", result.Split(new char[] { '_' }
, StringSplitOptions.RemoveEmptyEntries)); // remove duplicate underscores
}
希腊代码页(ISO)可以做到这一点
关于这个代码页的信息在System.Text.Encoding.GetEncodings()中。了解网址:https://msdn.microsoft.com/pt-br/library/system.text.encodinginfo.getencoding(v=vs.110).aspx
希腊语(ISO)的代码页为28597,名称为ISO -8859-7。
进入代码…\ o /
string text = "Você está numa situação lamentável";
string textEncode = System.Web.HttpUtility.UrlEncode(text, Encoding.GetEncoding("iso-8859-7"));
//result: "Voce+esta+numa+situacao+lamentavel"
string textDecode = System.Web.HttpUtility.UrlDecode(textEncode);
//result: "Voce esta numa situacao lamentavel"
那么,写这个函数…
public string RemoveAcentuation(string text)
{
return
System.Web.HttpUtility.UrlDecode(
System.Web.HttpUtility.UrlEncode(
text, Encoding.GetEncoding("iso-8859-7")));
}
请注意,…Encoding. getencoding ("iso-8859-7")等价于Encoding. getencoding(28597),因为第一个是Encoding的名称,第二个是Encoding的编码页。
这段代码对我很有用:
var updatedText = text.Normalize(NormalizationForm.FormD)
.Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
.ToArray();
但是,请不要对名字这样做。这不仅是对名字中有变音或口音的人的侮辱,在某些情况下也可能是危险的错误(见下文)。除了去掉重音,还有其他的写法。
此外,这是错误和危险的,例如,如果用户必须如实提供护照上的名字。
例如,我的名字写着Zuberbühler,在我护照的机读部分,你会发现祖伯布勒。去掉变音后,名字将与两个部分都不匹配。这可能会给用户带来问题。
您应该禁止在名字的输入表单中使用变音/重音,以便用户可以正确地书写没有变音或重音的名字。
例如,如果申请ESTA的web服务(https://www.application-esta.co.uk/special-characters-and)使用上述代码,而不是正确地转换变音,ESTA申请要么会被拒绝,要么旅行者在进入美国时将与美国边境控制出现问题。
另一个例子是机票。假设您有一个机票预订web应用程序,用户提供带有重音的名字,您的实现只是删除重音,然后使用航空公司的web服务预订机票!您的客户可能不被允许登机,因为姓名与他/她护照的任何部分不匹配。
公认的答案是完全正确的,但是现在,它应该更新为使用符文类而不是CharUnicodeInfo,因为c#和。net在最新版本中更新了分析字符串的方法(符文类已在。net Core 3.0中添加)。
下面的代码现在推荐用于。net 5+,因为它可以进一步用于非拉丁字符:
static string RemoveDiacritics(string text)
{
var normalizedString = text.Normalize(NormalizationForm.FormD);
var stringBuilder = new StringBuilder();
foreach (var c in normalizedString.EnumerateRunes())
{
var unicodeCategory = Rune.GetUnicodeCategory(c);
if (unicodeCategory != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}
与接受的答案相同,但更快,使用Span而不是StringBuilder。 需要。net Core 3.1或更新的。net。
static string RemoveDiacritics(string text)
{
ReadOnlySpan<char> normalizedString = text.Normalize(NormalizationForm.FormD);
int i = 0;
Span<char> span = text.Length < 1000
? stackalloc char[text.Length]
: new char[text.Length];
foreach (char c in normalizedString)
{
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
span[i++] = c;
}
return new string(span).Normalize(NormalizationForm.FormC);
}
此外,这是可扩展的额外字符替换,如抛光Ł。
span[i++] = c switch
{
'Ł' => 'L',
'ł' => 'l',
_ => c
};
一个小提示:堆栈分配stackalloc比堆分配new要快得多,它为垃圾收集器减少了工作。1000是一个阈值,以避免在堆栈上分配大结构,这可能会导致StackOverflowException。虽然1000是一个相当安全的值,但在大多数情况下10000甚至100000也可以(100k在堆栈上分配最多200kB,而默认堆栈大小为1mb)。然而10万对我来说有点危险。