【问题标题】:How to Naturally Sort a DataView with something like IComparable如何使用 IComparable 之类的东西自然地对 DataView 进行排序
【发布时间】:2010-09-10 12:55:42
【问题描述】:

我的 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;

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

【问题讨论】:

    标签: .net asp.net dataview icomparable


    【解决方案1】:

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

    附: 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 中工作,您不必复制数据。

    【讨论】:

      【解决方案2】:

      很丑,但是:

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

      NaturalComparerthis class

      【讨论】:

      • 无法将其复制并粘贴到我的应用中
      • 我看不出你还想要什么。
      • @aron - 从提供的链接中获取课程并将其保存在您的应用中。如果您已经有数据表,则此代码有效。只需更改 DataView dv = GetDataViewSomewhere();到 DataView dv = DatatableIalreadyHave.DefaultView;然后运行代码(将 COLUMN_TO_SORT_ON 的值更改为您需要排序的列之后)。然后最后你需要用 DatatableIalreadyHave = dv.ToTable(); 将数据发送回你的数据表;
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-08
      • 1970-01-01
      • 2014-09-23
      • 2014-08-26
      相关资源
      最近更新 更多