Порядок использованияBy в LINQ сначала кириллические слова, а затем латинские слова

var listExample = new List<string>(){ "banana", "apple", "lemon", "orange", 
"cherry", "pear", "яблоко", "лимон", "груша", "банан", "апельсин", "вишня" };
listExample = listExample.OrderBy(x => x).ToList();

Результат

{ "apple", "banana", "cherry", "lemon", "orange", "pear", "апельсин", "банан", "вишня", "груша", "лимон", "яблоко" }

Но сначала нужно заказать по русски, а потом по английски

{ "апельсин", "банан", "вишня", "груша", "лимон", "яблоко", "apple", "banana", "cherry", "lemon", "orange", "pear" }

Как использовать OrderBy для получения такого результата?

4 голоса | спросил Nikita Minaev 20 J0000006Europe/Moscow 2018, 09:48:25

3 ответа


0

Вы можете использовать проверку заказа, если работа latin.

Приведенный ниже код возвращает желаемый результат, где он проверяет, является ли слово IsCyrillic.

    var listExample = new List<string>(){ "banana", "apple", "lemon", "orange",  "cherry", 
                           "pear", "яблоко", "лимон", "груша", "банан", "апельсин", "вишня" };

    var result = listExample.OrderBy(x => x)
                    .Select(x => new {val = x, isCyrillic = Regex.IsMatch(x, @"\p{IsCyrillic}")})
                    .OrderBy(x => !x.isCyrillic).Select(x => x.val);

    foreach (var str in result)
    {
        Console.WriteLine(str);
    }

Проверьте полный код на этой скрипке - https://dotnetfiddle.net/9o4FJt

Вывод вышеуказанной программы -

  

апельсин   банан   вишня   груша   лимон   яблоко   яблоко   банан   вишня   лимон   оранжевый   груша

ответил user1672994 20 J0000006Europe/Moscow 2018, 10:11:00
0

Для довольно «быстрого и грязного» подхода я бы, вероятно, упорядочил по «первому индексу, содержащему кириллицу» (используя int.MaxValue для «нет кириллицы») с последующим регулярным упорядочением (что позволяет сделать его без учета регистра и т. д.).

Так что-то вроде:

var result = list.OrderBy(GetFirstCyrillicIndex).ThenBy(x => x).ToList();
...

private static int GetFirstCyrillicIndex(string text)
{
    // This could be written using LINQ, but it's probably simpler this way.
    for (int i = 0; i < text.Length; i++)
    {
        if (text[i] >= 0x400 && text[i] <= 0x4ff)
        {
            return i;
        }
    }
    return int.MaxValue;
}

Полный пример, включая мои неуклюжие слова:

using System;
using System.Collections.Generic;
using System.Linq;

class Test
{
    static void Main()
    {
        var list = new List<string> { 
            "banana", "apple", "lemon", "orange", 
            "cherry", "pear", "яблоко", "лимон",
            "груша", "банан", "апельсин", "вишня",
            "appleвишня", "вишняapple"
        };
        var result = list.OrderBy(GetFirstCyrillicIndex).ThenBy(x => x).ToList();
        foreach (var item in result)
        {
            Console.WriteLine(item);
        }
    }

    private static int GetFirstCyrillicIndex(string text)
    {
        // This could be written using LINQ, but it's probably simpler this way.
        for (int i = 0; i < text.Length; i++)
        {
            if (text[i] >= 0x400 && text[i] <= 0x4ff)
            {
                return i;
            }
        }
        return int.MaxValue;
    }
}

Результаты:

апельсин
банан
вишня
вишняapple
груша
лимон
яблоко
appleвишня
apple
banana
cherry
lemon
orange
pear
ответил Jon Skeet 20 J0000006Europe/Moscow 2018, 10:22:56
0

Ради альтернативы, если вы не хотите реализовывать совершенно новый метод заказного заказа, вы можете создать свой метод расширения и использовать существующие методы заказа:

public static class MyExtensions
{
     public static IEnumerable<string> OrderByCyrillicFirst(this IEnumerable<string> list)
     {
         var cyrillicOrderedList = list.Where(l => string.IsNullOrEmpty(l) ? false : IsCyrillic(l[0])).OrderBy(l => l);
         var latinOrderedList = list.Where(l => string.IsNullOrEmpty(l) ? true : !IsCyrillic(l[0])).OrderBy(l => l);
         return cyrillicOrderedList.Concat(latinOrderedList);
     }

     public static IEnumerable<string> OrderByCyrillicFirstDescending(this IEnumerable<string> list)
     {
         var cyrillicOrderedList = list.Where(l => string.IsNullOrEmpty(l) ? false : IsCyrillic(l[0])).OrderByDescending(l => l);
         var latinOrderedList = list.Where(l => string.IsNullOrEmpty(l) ? true : !IsCyrillic(l[0])).OrderByDescending(l => l);
         return cyrillicOrderedList.Concat(latinOrderedList);
     }

    //cyrillic symbols start with code 1024 and end with 1273.
    private static bool IsCyrillic(char ch) =>
        ch >= 1024 && ch <= 1273;       
}

и использование:

var listExample = new List<string>(){ "banana", "apple", "lemon", "orange", "cherry", "pear", "яблоко", "лимон", "груша", "банан", "апельсин", "вишня" };

var result = listExample.OrderByCyrillicFirst();

выход:

  

апельсин банан вишня груша лимон яблоко яблоко банан вишня лимон апельсин груша

Ссылки: Пример DotNetFiddle , Таблица кириллического юникода

ответил SeM 20 J0000006Europe/Moscow 2018, 10:52:47

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132