如何使用IComparable之类的方法对DataView进行自然排序
我的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"是此类。