Как Естественно Сортировать DataView с чем-то вроде IComparable - PullRequest
4 голосов
/ 18 сентября 2008

Мой DataView ведет себя забавно, сортирует вещи по алфавиту, и мне это нужно для числовой сортировки. Я искал во всем Интернете этот и нашел много идей о том, как отсортировать его с помощью ICompare, но ничего толкового.

Так что мои вопросы

  1. Как реализовать ICompare для DataView (ищите код здесь).
  2. Как правильно расшифровать столбец, полный строк, которые являются фактическими строками, и столбец, полный чисел (с запятыми).

Мне нужен код, чтобы помочь мне с этим, ребята. Я более или менее заблудился в идее ICompare и в том, как ее реализовать в различных сценариях, поэтому было бы неплохо дать хорошее объяснение.

Также, пожалуйста, не передавайте мне ссылки. Я ищу твердые ответы на этот вопрос.

Какой-то код, который я использую.

    DataView dataView = (DataView)Session["kingdomData"];
    dataView.Sort = e.SortExpression + " " + ConvertSortDirectionToSql(e.SortDirection);
    gvAllData.DataSource = dataView;
    gvAllData.DataBind();



    private string ConvertSortDirectionToSql(SortDirection sortDirection)
{
    string newSortDirection = String.Empty;
    if (Session["SortDirection"] == null)
    {
        switch (sortDirection)
        {
            case SortDirection.Ascending:
                newSortDirection = "ASC";
                break;
            case SortDirection.Descending:
                newSortDirection = "DESC";
                break;
        }
    }
    else
    {
        newSortDirection = Session["SortDirection"].ToString();
        switch (newSortDirection)
        {
            case "ASC":
                newSortDirection = "DESC";
                break;
            case "DESC":
                newSortDirection = "ASC";
                break;
        }
    }
    Session["SortDirection"] = newSortDirection;
    return newSortDirection;
}

Ответы [ 3 ]

3 голосов
/ 18 сентября 2008

Для первого вопроса - IIRC вы не можете сортировать DataView с помощью компаратора. Если вам просто нужно отсортировать поле численно, вы должны быть уверены, что тип столбца числовой, а не строковый. Некоторый код поможет разобраться в этом.

Для второго вопроса вы также не можете сделать это непосредственно в DataView. Если вам действительно нужно отсортировать записи на основе некоторой обработки данных в столбце, тогда я скопирую данные в массив и использую IComparer в массиве:

DataView dv = new DataView(dt);
ArrayList lst = new ArrayList();
lst.AddRange(dv.Table.Rows);
lst.Sort(new MyComparer());
foreach (DataRow dr in lst)
    Debug.WriteLine(dr[0]);

Сравнитель выглядит так:

    class MyComparer : IComparer
    {
        public int Compare(object x, object y)
        {
            DataRow rx = x as DataRow;
            DataRow ry = y as DataRow;
            string datax = (string)rx[colName];
            string datay = (string)ry[colName];
            // Process datax and datay here then compare them (ASC)
            return datax.CompareTo(datay);
        }
    }

Это увеличит потребление памяти, поэтому вам нужно подумать, возможно, есть лучший способ предварительной обработки данных в таблице, чтобы можно было напрямую отсортировать DataView по столбцу.

P.S. colName - это имя столбца, по которому вы хотите отсортировать. Замените комментарий фактическим кодом, чтобы извлечь информацию о сортировке из столбца. Вы также можете использовать этот метод для извлечения информации сортировки из нескольких столбцов. Просто используйте что-то вроде этого:

int cmp = colAx.CompareTo(colAy);
if (cmp != 0)
    return cmp;
cmp = colBy.CompareTo(colBx);
return cmp;

Это будет сравнивать возрастание по значениям colA и затем убывание по значениям colB (не то, что второе сравнение имеет сначала y , а затем x )

Редактировать : ОК, я неправильно истолковал термин, разделенный запятыми. Из вашего примера я думаю, что вы имели в виду числа с тысячами разделителей (1 000 000 = один миллион). Если вы храните такие числа в базе данных, то это должно быть то, что вы используете текстовое поле, и это должно быть причиной того, что ваш порядок сортировки является буквенно-цифровым.

Исходя из этого предположения, я бы предложил изменить тип этого столбца на числовой, сохранить обычные числа внутри и отформатировать их (с тысячами разделителей) только при их отображении. Таким образом, сортировка должна работать непосредственно в DataView, и вам не нужно копировать данные.

1 голос
/ 29 октября 2009

Это некрасиво, но:

        DataView dv = GetDataViewSomewhere();

        //Naturally sort by COLUMN_TO_SORT_ON
        try
        {
            List<string> rowList = new List<string>();
            foreach (DataRowView drv in dv)
                rowList.Add((string)drv["COLUMN_TO_SORT_ON"]);
            rowList.Sort(new NaturalComparer());
            Dictionary<string, int> sortValueHash = new Dictionary<string, int>();
            for (int i = 0; i < rowList.Count; i++)
                sortValueHash.Add(rowList[i], i);                                    

            dv.Table.Columns.Add("NATURAL_SORT_ORDER", typeof(int));
            foreach (DataRowView drv in dv)
                drv["NATURAL_SORT_ORDER"] = sortValueHash[(string)drv["COLUMN_TO_SORT_ON"]];
            dv.Sort = "NATURAL_SORT_ORDER";                
        }
        catch (Exception)
        {                
            DEBUG_TRACE("Could not naturally sort");
            dv.Sort = "COLUMN_TO_SORT_ON";
        }

Где NaturalComparer это этот класс .

0 голосов
/ 18 сентября 2008

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

Когда пользователь вызывает вид сетки для сортировки столбца, я вспоминаю представление данных в объекте сеанса и строю выражение сортировки представления данных следующим образом:

dataview.sort = e.sortexpression + " " + e.Sortdirection; 

Или что-то в этом роде. То, что обычно получается, подходит для всех реальных строк, таких как

Car; Главная; Скот; Зак и т.д ...

Но когда я делаю то же самое для числовых полей с разделенными запятыми значениями, получается что-то вроде

900; 800; 700; 600; 200; 120; 1200; 12340; 1000000;

Видишь, что я имею в виду? Он просто сортирует элементы как альфа-сортировку вместо натуральной. Я хочу, чтобы мой Dataview ЕСТЕСТВЕННО сортировал числовые столбцы, как

120; 200; 600; 700; 800; 900; 1200; 12340; 1000000;

Дайте мне знать, что вы можете сделать, чтобы помочь мне.
Постскриптум Я просмотрел бесчисленное множество статей о том, как это сделать, и все они говорят о том, чтобы добавить в список / массив и сделать это таким образом, но есть ли гораздо более эффективный способ?

...