LINQ и CASE Чувствительность - PullRequest
2 голосов
/ 16 марта 2011

У меня есть этот LINQ Query:

TempRecordList = new ArrayList(TempRecordList.Cast<string>().OrderBy(s => s.Substring(9, 30)).ToArray());

Отлично работает и выполняет сортировку точно, но немного отличается от того, что я хочу. Среди результатов запроса я вижу что-то вроде этого:

Palm-Bouter, Peter
Палмер-Джонсон, Шон

В то время как мне действительно нужно, чтобы имена сортировались следующим образом:

Палмер-Джонсон, Шон
Palm-Bouter, Питер

По сути, я хочу, чтобы символ '-' обрабатывался как находящийся ниже символа, чтобы имена, содержащие его, появлялись позже при поиске по возрастанию.

Вот еще один пример. Я получаю:

Диас, Реджинальд
ДиБлэкли, Антон

Вместо:

ДиБлэкли, Антон
Диас, Реджинальд

Как видите, опять порядок меняется из-за того, как обрабатывается заглавная буква "B".

Итак, мой вопрос: что мне нужно изменить в моем запросе LINQ, чтобы он возвращал результаты в указанном порядке. Любая обратная связь будет очень оценена.

Кстати, я пытался использовать s.Substring (9, 30) .ToLower () , но это не помогло.

Спасибо!

Ответы [ 4 ]

6 голосов
/ 16 марта 2011

Чтобы настроить порядок сортировки, вам нужно создать класс сравнения, который реализует интерфейс IComparer<string>. Метод OrderBy() принимает компаратор в качестве второго параметра.

internal sealed class NameComparer : IComparer<string> {
    private static readonly NameComparer DefaultInstance = new NameComparer();

    static NameComparer() { }
    private NameComparer() { }

    public static NameComparer Default {
        get { return DefaultInstance; }
    }

    public int Compare(string x, string y) {
        int length = Math.Min(x.Length, y.Length);
        for (int i = 0; i < length; ++i) {
            if (x[i] == y[i]) continue;
            if (x[i] == '-') return 1;
            if (y[i] == '-') return -1;
            return x[i].CompareTo(y[i]);
        }

        return x.Length - y.Length;
    }
}

Это работает по крайней мере для следующих тестовых случаев:

var names = new[] {
    "Palmer-Johnson, Sean",
    "Palm-Bouter, Peter",
    "Dias, Reginald",
    "DiBlackley, Anton",
};

var sorted = names.OrderBy(name => name, NameComparer.Default).ToList();

// sorted:
// [0]: "DiBlackley, Anton"
// [1]: "Dias, Reginald"
// [2]: "Palmer-Johnson, Sean"
// [3]: "Palm-Bouter, Peter"
2 голосов
/ 17 мая 2016

Как уже упоминалось, метод OrderBy() принимает компаратор в качестве второго параметра.

Для строк вам необязательно реализовывать IComparer<string>.Возможно, вам будет хорошо с System.StringComparer.CurrentCulture (или одним из других в System.StringComparer).

Однако в вашем конкретном случае нет встроенного компаратора, который будет обрабатывать также - после письмо порядок сортировки.

0 голосов
/ 16 марта 2011

Возможно, вы захотите просто реализовать собственный объект IComparer, который будет отдавать пользовательский приоритет специальным, прописным и строчным буквам.

http://msdn.microsoft.com/en-us/library/system.collections.icomparer.aspx

0 голосов
/ 16 марта 2011

OrderBy() возвращает результаты в порядке возрастания.

e предшествует h, таким образом, первый результат (помните, что вы сравниваете подстроку, начинающуюся с символа в 9-й позиции ... не начала строки), а i предшествует y, таким образом, второе. Чувствительность к регистру не имеет к этому никакого отношения.

Если вы хотите получить результаты в порядке убывания, вы должны использовать OrderByDescending():

TempRecordList.Cast<string>
              .OrderByDescending(s => s.Substring(9, 30)).ToArray());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...