如何使用 IComparable 之类的方法自然地对 DataView 进行排序

发布于 2024-07-04 11:31:42 字数 2159 浏览 7 评论 0原文

我的 DataView 表现得很有趣,它按字母顺序对事物进行排序,而我需要它按数字对事物进行排序。 我在整个网络上查找了这个问题,发现了很多关于如何使用 ICompare 对其进行排序的想法,但没有什么真正可靠的。

所以我的问题是

  1. 如何在 DataView 上实现 ICompare(在此处查找代码)。
  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;
}

对于该场景,我动态构建一个数据表并将其推入数据视图中,在其中将数据视图放入网格视图中,同时还记得将数据视图放入会话对象中以实现排序功能。

当用户调用 gridview 对列进行排序时,我会调用会话对象中的 dataview 并构建如下所示的 dataview 排序表达式:

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

或者类似的内容。 因此,通常结果对于所有真实字符串(例如

Car)都是正确的; 家; 斯科特; zach 等...

但是当我对带有逗号分隔值的数字字段执行相同操作时,结果会类似于

900; 800; 700; 600; 200; 120; 1,200; 12,340; 1,000,000;

明白了吗? 它只是将项目排序为 alpha 排序而不是自然排序。 我想让我的 Dataview 自然地对数字列进行正确排序,例如

120; 200; 600; 700; 800; 900; 1,200; 12,340; 1,000,000;

让我知道你可以做些什么来帮助我。
PS我已经浏览了无数关于如何做到这一点的文章,他们都说要推入列表/数组并这样做,但是有没有更有效的方法呢?

My DataView is acting funny and it is sorting things alphabetically and I need it to sort things numerically. I have looked all across the web for this one and found many ideas on how to sort it with ICompare, but nothing really solid.

So my questions are

  1. How do I implement ICompare on a DataView (Looking for code here).
  2. How to correctly decipher from a column full of strings that are actual strings and a column full of numbers(with commas).

I need code to help me out with this one guys. I am more or less lost on the idea of ICompare and how to implement in different scenarios so an over all good explanation would be great.

Also, Please don't hand me links. I am looking for solid answers on this one.

Some Code that I use.

    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;
}

For the scenario, I build a datatable dynamically and shove it into a dataview where I put the dataview into a gridview while also remembering to put the dataview into a session object for sorting capabilities.

When the user calls on the gridview to sort a column, I recall the dataview in the session object and build the dataview sorting expression like this:

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

Or something along those lines. So what ussually comes out is right for all real strings such as

Car; Home; scott; zach etc...

But when I do the same for number fields WITH comma seperated values it comes out something like

900; 800; 700; 600; 200; 120; 1,200; 12,340; 1,000,000;

See what I mean? It just sorts the items as an alpha sort instead of a Natural sort. I want to make my Dataview NATURALLY sort the numeric columns correctly like

120; 200; 600; 700; 800; 900; 1,200; 12,340; 1,000,000;

Let me know what you can do to help me out.
P.S. I have looked through countless articles on how to do this and all of them say to shove into a List/Array and do it that way, but is there a much more efficient way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

司马昭之心 2024-07-11 11:31:42

对于第一个问题 - 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 进行排序。

PS 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 中进行,而不必复制数据。

For the first issue - IIRC you can't sort a DataView with a comparer. If you just need to sort numerically a field you must be sure that the column type is numeric and not string. Some code would help to elucidate this.

For the second issue also you can't do that directly in the DataView. If you really need to sort the records based on some processing of data in a column then I'd copy the data in an array and use an IComparer on the array:

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]);

The comparer is like this:

    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);
        }
    }

This will increase the memory consumption, so you need to think if there is maybe a better way to preprocess the data in the table so that you can sort directly the DataView by a column.

P.S. colName is the name of the column you're interested to sort by. Replace the comment with actual code to extract the sorting info from the column. You can also use this method to extract sorting info from more columns. Just use something like this:

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

This will compare ascending by colA values and then descending by colB values (not that the second compare has y first and then x)

Edit: OK, I interpreted wrongly the term comma separated values. From your example I think that you actually meant numbers with thousand separators (1,000,000 = one million). If you store numbers like this in the database then it must be that you're using a text field and that should be the reason your sorting order is alphanumeric.

Based on this assumption I would propose to change the type of that column to numeric, keep normal numbers inside and format them (with thousand separators) only when you display them. This way the sort should work directly in the DataView and you don't have to copy the data.

很酷不放纵 2024-07-11 11:31:42

它很丑陋,但是:

        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此类

It's ugly, but:

        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";
        }

Where NaturalComparer is this class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文