为什么我的 DataTable.DefaultView.Sort 不按顺序排序?



所以我正在尝试对一些数据进行排序并打印它,但DataTable.DefaultView.Sort似乎无法按照我期望的方式工作。鉴于此数据:

Col1    Col2    Col3
2802    32      0
2802    80      3
2802    130     3
2802    40      0
2802    40      0
2802    35      0

并按"Col2"排序,我得到:

2802    130     3
2802    32      0
2802    35      0
2802    40      0
2802    40      0
2802    80      3

我写了一个简单的排名库来完成我的期望(DataTableRanker.Framework.Util),它在这个代码片段下面,但它只按 1 列排序,我更喜欢使用.Sort = Col1, Col2, Col3,等:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using DataTableRanker.Framework.Util;
namespace Test
{
class Program
{
static void Main(string[] args)
{
DataTable testTable = new DataTable();
testTable.Columns.Add("FacilityID");
testTable.Columns.Add("FromDimensions");
testTable.Columns.Add("FromAttributeName");
DataRow dr1 = testTable.NewRow();
dr1["FacilityID"] = "2802";
dr1["FromDimensions"] = 4*8;
dr1["FromAttributeName"] = 0;
testTable.Rows.Add(dr1);
DataRow dr2 = testTable.NewRow();
dr2["FacilityID"] = "2802";
dr2["FromDimensions"] = 8*10;
dr2["FromAttributeName"] = 3;
testTable.Rows.Add(dr2);
DataRow dr3 = testTable.NewRow();
dr3["FacilityID"] = "2802";
dr3["FromDimensions"] = 10*13;
dr3["FromAttributeName"] = 3;
testTable.Rows.Add(dr3);
DataRow dr4 = testTable.NewRow();
dr4["FacilityID"] = "2802";
dr4["FromDimensions"] = 4*10;
dr4["FromAttributeName"] = 0;
testTable.Rows.Add(dr4);
DataRow dr5 = testTable.NewRow();
dr5["FacilityID"] = "2802";
dr5["FromDimensions"] = 4 * 10;
dr5["FromAttributeName"] = 0;
testTable.Rows.Add(dr5);
DataRow dr6 = testTable.NewRow();
dr6["FacilityID"] = "2802";
dr6["FromDimensions"] = 5*7;
dr6["FromAttributeName"] = 0;
testTable.Rows.Add(dr6);
DataTable copyTestTable;
copyTestTable = testTable.Copy();
copyTestTable.Columns.Add("Ranking");
Console.Write("-- Not Sorted --");
Console.WriteLine();
foreach (DataRowView dr in testTable.DefaultView)
{
for (int i = 0; i < testTable.DefaultView.Table.Columns.Count; i++)
Console.Write(dr[i] + "t");
Console.WriteLine();
}
testTable.DefaultView.Sort = "FromDimensions";
Console.Write("-- Sorted --");
Console.WriteLine();
foreach (DataRowView dr in testTable.DefaultView)
{
for (int i = 0; i < testTable.DefaultView.Table.Columns.Count; i++)
Console.Write(dr[i] + "t");
Console.WriteLine();
}
Console.Write("-- Ranked with System.Data --");
Console.WriteLine();
testTable.Columns.Add(new DataColumn("Rank", typeof(int)));
int count = 1;
foreach (DataRowView dr in testTable.DefaultView)
{
dr["Rank"] = count++;
}
foreach (DataRowView dr in testTable.DefaultView)
{
for (int i = 0; i < testTable.DefaultView.Table.Columns.Count; i++)
Console.Write(dr[i] + "t");
Console.WriteLine();
}
Console.Write("-- Ranked with DataTableRanker --");
Console.WriteLine();
DataTableSort u1 = new DataTableSort();
u1.RankDataTable(ref copyTestTable, "FromDimensions", "Ranking");
copyTestTable.DefaultView.Sort = "Ranking";
foreach (DataRowView dr in copyTestTable.DefaultView)
{
for (int i = 0; i < copyTestTable.DefaultView.Table.Columns.Count; i++)
Console.Write(dr[i] + "t");
Console.WriteLine();
}
}
}
}

这是DataTableRanker.Framework.Util

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
namespace DataTableRanker.Framework.Util
{
public class DataTableSort
{
public void RankDataTable(ref DataTable toOperateDataTable, string sortByValue, string rankingValue)
{
// group data elements
List<RankGroup> rgc = new List<RankGroup>();
foreach (DataRow dr1 in toOperateDataTable.Rows)
{
RankGroup g1 = new RankGroup();
foreach (DataRow dr2 in toOperateDataTable.Rows)
{
if (dr1 != dr2 && dr2 != null)
{
if (!g1.Index.Contains(toOperateDataTable.Rows.IndexOf(dr1)))
{
g1.Index.Add(toOperateDataTable.Rows.IndexOf(dr1));
g1.Score = float.Parse((string)dr1[sortByValue]);
}
if ((float.Parse((string)dr1[sortByValue]) == float.Parse((string)dr2[sortByValue]) && !g1.Index.Contains(toOperateDataTable.Rows.IndexOf(dr2))))
{
g1.Index.Add(toOperateDataTable.Rows.IndexOf(dr2));
g1.Score = float.Parse((string)dr2[sortByValue]);
}                        
}
}
if (!ExistsIndexes(rgc, g1))
rgc.Add(g1);
}
List<RankGroup> sortedRankGroup = rgc.OrderByDescending(t => t.Score).ToList();
int ranking = 1;
foreach (RankGroup rg in sortedRankGroup)
{
foreach (int i in rg.Index)
{
toOperateDataTable.Rows[i][rankingValue] = ranking;
}
ranking++;
}            
}
bool ExistsIndexes(List<RankGroup> rgc, RankGroup rg)
{
foreach (RankGroup trg in rgc)
{
foreach (int i in rg.Index)
{
if (trg.Index.Any(t => t == i))
return true;
}
}
return false;
}
internal class RankGroup
{
// string sortByFiled;
float score;
List<int> indexes = new List<int>();
int ranking;
public float Score
{
get { return score; }
set { score = value; }
}
public List<int> Index
{
get { return indexes; }
set { indexes = value; }
}
public int Ranking
{
get { return ranking; }
set { ranking = value; }
}
}
}
}

任何帮助或解释都非常感谢!

正如注释中所建议的,排序顺序是基于字符串的。 1 在 3 之前,所以 130 出现在 31 之前。 这是添加没有其他选项的新列时的默认行为

在 DataTable 类文档的示例中,首先了解如何创建列,并设置其数据类型。

column = new DataColumn();
column.DataType = System.Type.GetType("System.Int32");
table.Columns.Add(column);

更新: 感谢ESG在评论中指出DataColumnCollection.Add具有也将采用类型的重载。

最新更新