4

我的 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 对列进行排序时,我会调用 session 对象中的 dataview 并构建 dataview 排序表达式,如下所示:

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

或类似的规定。所以通常出现的结果适用于所有真实字符串,例如

车; 家; 斯科特; 扎克之类的……

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

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我浏览了无数关于如何做到这一点的文章,他们都说要塞入一个列表/数组并这样做,但是有没有更有效的方法?

4

2 回答 2

3

对于第一个问题 - 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 中工作,您不必复制数据。

于 2008-09-18T06:26:48.687 回答
1

这很丑陋,但是:

        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堂课在哪里。

于 2009-10-28T23:41:03.210 回答