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

时间:2020-03-06 14:19:57  来源:igfitidea点击:

我的DataView表现滑稽,它按字母顺序对事物进行排序,而我需要它按数字对事物进行排序。我已经在网上寻找了这一内容,并发现了许多有关如何使用ICompare对其进行排序的想法,但并没有真正可靠的方法。

所以我的问题是

  • 如何在DataView上实现ICompare(在此处查找代码)。
  • 如何从包含实际字符串的一列和包含数字(带逗号)的一列中正确地解密。

我需要代码来帮助我解决这个问题。我或者多或者少对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;
}

解决方案

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

对于这种情况,我动态地构建了一个数据表,并将其推入数据视图,然后将数据视图放入网格视图中,同时还记得将数据视图放入会话对象中以进行排序。

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

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

或者类似的规定。因此,通常情况下输出的结果适用于所有实际字符串,例如

车;家;斯科特扎克等...

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

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

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

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

让我知道我们可以采取什么措施来帮助我。
P.S.我浏览了无数有关如何执行此操作的文章,所有这些人都说要推入List / Array并以这种方式进行操作,但是有没有更有效的方法?

很难看,但是:

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"是此类。