OrderBy 忽略重音字母
OrderBy ignoring accented letters
我想要一种像 OrderBy()
这样的方法,它总是命令忽略带重音的字母并将它们视为非重音字母。我已经尝试覆盖 OrderBy()
但似乎我不能这样做,因为那是一个静态方法。
所以现在我想为 OrderBy()
创建一个自定义 lambda 表达式,如下所示:
public static IOrderedEnumerable<TSource> ToOrderBy<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
if(source == null)
return null;
var seenKeys = new HashSet<TKey>();
var culture = new CultureInfo("pt-PT");
return source.OrderBy(element => seenKeys.Add(keySelector(element)),
StringComparer.Create(culture, false));
}
但是,我遇到了这个错误:
Error 2 The type arguments for method
'System.Linq.Enumerable.OrderBy<TSource,TKey>(System.Collections.Generic.IEnumerable<TSource>,
System.Func<TSource,TKey>,
System.Collections.Generic.IComparer<TKey>)' cannot be inferred from
the usage. Try specifying the type arguments explicitly.
好像不喜欢StringComparer
。我该如何解决这个问题?
注:
我已经尝试使用 here but I don't know how to use that method in this case. So I tried to do something like this 中的 RemoveDiacritics()
,这看起来也不错。
OrderBy
将 keySelector
作为第一个参数。这个keySelector
应该是一个Func<string,T>
。因此,您需要一个方法,该方法接受一个字符串和 returns 一个 值,您的枚举应按该值进行排序 .
不幸的是,我不确定如何确定一个字符是否为 "accented letter"。 RemoveDiacritics
不适用于我的 é
。
因此,假设您有一个名为 IsAccentedLetter
的方法来确定字符是否为重音字母:
public bool IsAccentedLetter(char c)
{
// I'm afraid this does NOT really do the job
return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.NonSpacingMark;
}
因此您可以这样对列表进行排序:
string[] myStrings = getStrings(); // whereever your strings come from
var ordered = myStrings.OrderBy(s => new string(s.Select(c =>
IsAccentedLetter(c) ? ' ' : c).ToArray()), StringComparer.Create(culture, false));
lambda 表达式接受一个字符串和 returns 相同的字符串,但用空 space.
替换重音字母
OrderBy
现在按这些字符串对您的枚举进行排序,"ignores" 重音字母也是如此。
更新: 如果你有一个工作方法 RemoveDiacritics(string s)
returns 根据需要替换带重音字母的字符串,你可以简单地调用 OrderBy
像这样:
string[] mystrings = getStrings();
var ordered = myStrings.OrderBy(RemoveDiacritics, StringComparer.Create(culture, false));
已解决!我收到该错误是因为要使用 StringComparer
元素在 OrderBy()
表达式中排序,该元素需要是 string
.
因此,当我知道该元素是一个字符串时,我将其转换为一个字符串,并使用 RemoveDiacritics()
方法忽略重音字母并将它们视为非重音字母。
public static IOrderedEnumerable<TSource> ToOrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
if(!source.SafeAny())
return null;
return source.OrderBy(element => Utils.RemoveDiacritics(keySelector(element).ToString()));
}
为了保证 RemoveDiacritics()
正常工作,我添加了 HtmlDecode()
行。
public static string RemoveDiacritics(string text)
{
if(text != null)
text = WebUtility.HtmlDecode(text);
string formD = text.Normalize(NormalizationForm.FormD);
StringBuilder sb = new StringBuilder();
foreach (char ch in formD)
{
UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(ch);
if (uc != UnicodeCategory.NonSpacingMark)
{
sb.Append(ch);
}
}
return sb.ToString().Normalize(NormalizationForm.FormC);
}
我想要一种像 OrderBy()
这样的方法,它总是命令忽略带重音的字母并将它们视为非重音字母。我已经尝试覆盖 OrderBy()
但似乎我不能这样做,因为那是一个静态方法。
所以现在我想为 OrderBy()
创建一个自定义 lambda 表达式,如下所示:
public static IOrderedEnumerable<TSource> ToOrderBy<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
if(source == null)
return null;
var seenKeys = new HashSet<TKey>();
var culture = new CultureInfo("pt-PT");
return source.OrderBy(element => seenKeys.Add(keySelector(element)),
StringComparer.Create(culture, false));
}
但是,我遇到了这个错误:
Error 2 The type arguments for method 'System.Linq.Enumerable.OrderBy<TSource,TKey>(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,TKey>, System.Collections.Generic.IComparer<TKey>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
好像不喜欢StringComparer
。我该如何解决这个问题?
注:
我已经尝试使用 here but I don't know how to use that method in this case. So I tried to do something like this 中的 RemoveDiacritics()
,这看起来也不错。
OrderBy
将 keySelector
作为第一个参数。这个keySelector
应该是一个Func<string,T>
。因此,您需要一个方法,该方法接受一个字符串和 returns 一个 值,您的枚举应按该值进行排序 .
不幸的是,我不确定如何确定一个字符是否为 "accented letter"。 RemoveDiacritics
不适用于我的 é
。
因此,假设您有一个名为 IsAccentedLetter
的方法来确定字符是否为重音字母:
public bool IsAccentedLetter(char c)
{
// I'm afraid this does NOT really do the job
return CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.NonSpacingMark;
}
因此您可以这样对列表进行排序:
string[] myStrings = getStrings(); // whereever your strings come from
var ordered = myStrings.OrderBy(s => new string(s.Select(c =>
IsAccentedLetter(c) ? ' ' : c).ToArray()), StringComparer.Create(culture, false));
lambda 表达式接受一个字符串和 returns 相同的字符串,但用空 space.
替换重音字母
OrderBy
现在按这些字符串对您的枚举进行排序,"ignores" 重音字母也是如此。
更新: 如果你有一个工作方法 RemoveDiacritics(string s)
returns 根据需要替换带重音字母的字符串,你可以简单地调用 OrderBy
像这样:
string[] mystrings = getStrings();
var ordered = myStrings.OrderBy(RemoveDiacritics, StringComparer.Create(culture, false));
已解决!我收到该错误是因为要使用 StringComparer
元素在 OrderBy()
表达式中排序,该元素需要是 string
.
因此,当我知道该元素是一个字符串时,我将其转换为一个字符串,并使用 RemoveDiacritics()
方法忽略重音字母并将它们视为非重音字母。
public static IOrderedEnumerable<TSource> ToOrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
if(!source.SafeAny())
return null;
return source.OrderBy(element => Utils.RemoveDiacritics(keySelector(element).ToString()));
}
为了保证 RemoveDiacritics()
正常工作,我添加了 HtmlDecode()
行。
public static string RemoveDiacritics(string text)
{
if(text != null)
text = WebUtility.HtmlDecode(text);
string formD = text.Normalize(NormalizationForm.FormD);
StringBuilder sb = new StringBuilder();
foreach (char ch in formD)
{
UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(ch);
if (uc != UnicodeCategory.NonSpacingMark)
{
sb.Append(ch);
}
}
return sb.ToString().Normalize(NormalizationForm.FormC);
}