OrderBy忽略重音字母

时间:2016-01-28 12:28:18

标签: c# sorting lambda expression 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));
} 

但是,我收到了这个错误:

  

错误2方法的类型参数   “System.Linq.Enumerable.OrderBy&LT; TSource,TKEY的&GT;(System.Collections.Generic.IEnumerable&LT; TSource&gt;中   System.Func&LT; TSource,TKEY的&gt;中   无法从中推断出System.Collections.Generic.IComparer&lt; TKey&gt;)'   用法。尝试明确指定类型参数。

似乎不喜欢StringComparer。我怎么解决这个问题?

注意:

我已经尝试使用here中的RemoveDiacritics()但我不知道在这种情况下如何使用该方法。所以我尝试做类似this的事情,这看起来也不错。

2 个答案:

答案 0 :(得分:2)

OrderBykeySelector作为第一个参数。此keySelector应为Func<string,T>。因此,您需要一个接受字符串并返回值的方法,通过该值可以对枚举进行排序

不幸的是,我不确定如何判断一个角色是否是一个重音字母&#34;。 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));

所以你可以像这样排序你的列表:

OrderBy

lambda表达式接受一个字符串并返回相同的字符串,但用空格替换带重音的字母 RemoveDiacritics(string s)现在按这些字符串对您的枚举进行排序,因此&#34;忽略&#34;重音字母。

更新:如果您有一个工作方法OrderBy,可以根据需要返回带有重音字母的字符串,您可以像这样简单地调用string[] mystrings = getStrings(); var ordered = myStrings.OrderBy(RemoveDiacritics, StringComparer.Create(culture, false));

{{1}}

答案 1 :(得分:2)

解决!我收到了这个错误,因为要使用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);
}