Как фильтровать C# Datatable с пустыми значениями столбца как последний - PullRequest
1 голос
/ 16 апреля 2020

У меня есть данные C# с 1000 строк. Но первичные 200 строк имеют пустые значения (несколько столбцов). Фильтр будет происходить с этими столбцами как пустые значения, чтобы занимать как последний. Я хочу, чтобы вывод происходил с таблицей или новой таблицей с фильтром, но не в виде строк linq. Пожалуйста, помогите мне

Изображения говорят больше слов, обратитесь к этому для лучшего понимания:

image

1 Ответ

0 голосов
/ 16 апреля 2020

Здесь необходимо учесть 2 вещи:

  1. " Пустое значение" : для сортировки элементов, за которыми следуют пустые столбцы значений, необходимо .OrderBy(s => String.IsNullOrEmpty(s["OrderNo"].ToString()))
  2. " Формат номера заказа ": для сортировки номера пользовательского заказа необходимо использовать IComparer<string>. Как вы показываете в своем вопросе, я предполагаю, что формат для Order No может быть XXXXX или XXXX-XXXX.

Так что вам нужно сначала OrderBy пустые значения ThenBy ваши пользовательские IComparer<string> что-то вроде этого:

public class OrderNoComparer : IComparer<string>
{
    public int Compare(string x, string y)
    {
        int xFirstValue = 0;
        int xSecondValue = 0;

        int yFirstValue = 0;
        int ySecondValue = 0;

        if (x.Contains("-"))
        {
            xFirstValue = Convert.ToInt32(x.Split(new char[] { '-' })[0]);
            xSecondValue = Convert.ToInt32(x.Split(new char[] { '-' })[1]);
        }
        else
        {
            xFirstValue = Convert.ToInt32(x);
        }

        if (y.Contains("-"))
        {
            yFirstValue = Convert.ToInt32(y.Split(new char[] { '-' })[0]);
            ySecondValue = Convert.ToInt32(y.Split(new char[] { '-' })[1]);
        }
        else
        {
            yFirstValue = Convert.ToInt32(y);
        }


        if (xFirstValue > yFirstValue)
        {
            return 1;
        }
        else if (xFirstValue < yFirstValue)
        {
            return -1;
        }
        else //means equal
        {
            if (xSecondValue > ySecondValue)
            {
                return 1;
            }
            else if (xSecondValue == ySecondValue)
            {
                return 0;

            }
            else
            {
                return -1;
            }
        }
    }
}

Полный пример здесь:

DataTable dtOrder = new DataTable();
dtOrder.Columns.Add("OrderNo");

var dr1 = dtOrder.NewRow();
dr1["OrderNo"] = "";
dtOrder.Rows.Add(dr1);

var dr2 = dtOrder.NewRow();
dr2["OrderNo"] = "569-875";
dtOrder.Rows.Add(dr2);

var dr3 = dtOrder.NewRow();
dr3["OrderNo"] = "569975";
dtOrder.Rows.Add(dr3);

var dr4 = dtOrder.NewRow();
dr4["OrderNo"] = "569865";
dtOrder.Rows.Add(dr4);

var dr5 = dtOrder.NewRow();
dr5["OrderNo"] = "569-975";
dtOrder.Rows.Add(dr5);

var dr6 = dtOrder.NewRow();
dr6["OrderNo"] = "569-875";
dtOrder.Rows.Add(dr6);


var result = dtOrder.AsEnumerable().AsQueryable()
                .OrderBy(s => String.IsNullOrEmpty(s["OrderNo"].ToString()))
                .ThenBy(o => o["OrderNo"].ToString(), new OrderNoComparer())
                .ToList();

foreach (var item in result)
{
    Console.WriteLine(item["OrderNo"]);
}

Тогда результат будет таким, как вы ожидали:

569-875
569-875
569-975
569865
569975
...