根据其中一个字段重新排序数据表的所有行
Reordering all rows of a datatable based on one of the fields
我有一个包含如下列的数据表:
Field1 | val 1 | val 2 | val 3
Field2 | val 1 | val 2 | val 3
Field3 | val 1 | val 2 | val 3
Field4 | val 1 | val 2 | val 3
等等..一直到Field20
在绑定到我页面上的网格之前完全重新排序行的最佳方法是什么。我会使用“字段”列来确定每一行的位置。
我做了研究,发现唯一的技术之一是克隆、删除、重新插入该行。
如果我必须对所有行执行此操作,因为 none 行处于正确位置,有人有好的方法吗?
这是我尝试过的:
DataTable dataTable2 = new DataTable();
DataRow[] row = dataTable1.Select("Field ='" + "Field2" +"'");
dataTable2 .Rows.InsertAt(row, 0);
您可以使用 LINQ 对 DataTable 进行排序。 LINQ 操作 (dt2) 的结果是 IEnumerable,但您仍然可以用它来绑定您的网格。
var dt = new DataTable();
dt.Columns.Add("Key", typeof(string));
dt.Columns.Add("Position", typeof(int));
dt.Rows.Add("Key1Value", 2);
dt.Rows.Add("Key2Value", 3);
dt.Rows.Add("Key3Value", 4);
dt.Rows.Add("Key4Value", 5);
dt.Rows.Add("Key5Value", 0);
dt.Rows.Add("Key6Value", 1);
var dt2 = dt.AsEnumerable().OrderBy(x => x.Field<int>("Position"));
foreach (DataRow dr in dt2)
{
Console.WriteLine("{0} {1}", dr["Key"], dr["Position"]);
}
我编辑了我的代码,使其符合您的排序顺序。我添加了一个名为 Position 的列,因此我可以根据需要对其进行排序。如果您想要不同的顺序,只需更改 Position 的值即可。
如果不想添加额外的列,可以在OrderBy方法中使用switch语句。
var dt = new DataTable();
dt.Columns.Add("Key", typeof(string));
dt.Rows.Add("Key1Value");
dt.Rows.Add("Key2Value");
dt.Rows.Add("Key3Value");
dt.Rows.Add("Key4Value");
dt.Rows.Add("Key5Value");
dt.Rows.Add("Key6Value");
var dt2 = dt.AsEnumerable().OrderBy(x =>
{
switch (x.Field<string>("Key"))
{
case "Key5Value": return 0;
case "Key6Value": return 1;
case "Key1Value": return 2;
case "Key2Value": return 3;
case "Key3Value": return 4;
case "Key4Value": return 5;
default : return -1;
}
}
);
foreach (DataRow dr in dt2)
{
Console.WriteLine(dr["Key"]);
}
基本上,OrderBy() 方法接受定义排序顺序的匿名方法。既然"Key5Value" returns 0,那么放在"Key6Value"(returns 1)之前。如果要从最大值到最小值对其进行排序,请使用 OrderByDescending() 方法。
我也编辑了你的代码。 getPosition 方法类似于我的 LINQ 代码中的 OrderBy() 方法。
using System;
using System.Data;
using System.Linq;
class Program
{
static void Main()
{
var dt = new DataTable();
dt.Columns.Add("Key", typeof(string));
dt.Rows.Add("Key1Value");
dt.Rows.Add("Key2Value");
dt.Rows.Add("Key3Value");
dt.Rows.Add("Key4Value");
dt.Rows.Add("Key5Value");
dt.Rows.Add("Key6Value");
var dt2 = dt.Clone();
foreach (DataRow dr in dt.Rows)
{
string key = dr["Key"].ToString();
var dRow = dt2.NewRow();
dRow.ItemArray = dr.ItemArray;
dt2.Rows.InsertAt(dRow, getPosition(key));
}
foreach (DataRow dr in dt2.Rows)
{
Console.WriteLine(dr["Key"]);
}
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
static int getPosition(string key)
{
switch (key)
{
case "Key5Value":
return 0;
case "Key6Value":
return 1;
case "Key1Value":
return 2;
case "Key2Value":
return 3;
case "Key3Value":
return 4;
case "Key4Value":
return 5;
default:
return -1;
}
}
}
版本 2:
我添加了一个包含键值(例如 Key1Value)和一对值的字典。对值是新的键值(例如键 1 值)和位置。我使用字典的原因是为了替换 switch-case 表达式。如果你愿意,你可以增加额外的价值。只需向元组添加更多类型即可。
Tuple<string, int, int, bool> // holds a sequence of a string, two integers and a boolean.
这是完整的代码。
using System;
using System.Data;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
// create table
var dt = new DataTable();
dt.Columns.Add("Key", typeof(string));
dt.Columns.Add("Val1", typeof(int));
dt.Columns.Add("Val2", typeof(int));
dt.Columns.Add("Val3", typeof(int));
dt.Columns.Add("Position", typeof(int));
// populate table
dt.Rows.Add("Key1Value", 100, 200, 300);
dt.Rows.Add("Key2Value", 100, 200, 300);
dt.Rows.Add("Key3Value", 100, 200, 300);
dt.Rows.Add("Key4Value", 100, 200, 300);
dt.Rows.Add("Key5Value", 100, 200, 300);
dt.Rows.Add("Key6Value", 100, 200, 300);
// initialize dictionary
var dict = new Dictionary<string, Tuple<string, int>>() {
{ "Key1Value", new Tuple<string, int>("Key 1 Value", 2) }, // Key1Value's new value is Key 1 Value, position is 2
{ "Key2Value", new Tuple<string, int>("Key 2 Value", 3) },
{ "Key3Value", new Tuple<string, int>("Key 3 Value", 4) },
{ "Key4Value", new Tuple<string, int>("Key 4 Value", 5) },
{ "Key5Value", new Tuple<string, int>("Key 5 Value", 0) },
{ "Key6Value", new Tuple<string, int>("Key 6 Value", 1) }
};
// set position and new key value
dt.AsEnumerable()
.ToList()
.ForEach(x => {
x["Position"] = dict[x.Field<string>("Key")].Item2;
x["Key"] = dict[x.Field<string>("Key")].Item1; // must be the last because the dictionary key is "KeyXValue", not "Key X Value"
});
// sort by Position
var dt2 = dt.AsEnumerable().OrderBy(x => x.Field<int>("Position"));
foreach (DataRow dr in dt2)
{
Console.WriteLine("{0}, {1}, {2}, {3}, {4}", dr["Key"], dr["Val1"], dr["Val2"], dr["Val3"], dr["Position"]);
}
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
由于时间因素,这是我能想到的最佳解决方案。如果您觉得可以用更好的方式完成,请发表评论。
此技术涉及创建源数据表的克隆。然后循环遍历源数据表并按所需顺序将行重新添加到 datatable2。
// Make a clone of the source datatable
DataTable dataTable2 = dataTable1.Clone();
// Loop through each row in the source datatable and check for key
foreach (DataRow dr in dataTable1.Rows)
{
string key = dr["Key"].ToString();
DataRow dRow = dataTable2.NewRow();
switch (key)
{
case "Key5Value":
// Rename actual key value if needed
dr["Key"] = "Key Rename if needed";
// Set new datarow item array to current row in loop item array
dRow.ItemArray = dr.ItemArray;
// Add datarow to desired position in dataTable 2
dataTable2.Rows.InsertAt(dRow, 0);
break;
case "Key6Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 1);
break;
case "Key1Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 2);
break;
case "Key2Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 3);
break;
case "Key4Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 4);
break;
case "Key3Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 5);
break;
}
}
另一种解决方案可能是:
- 在数据 table 中添加一个新列 "IntegerKey"。
- 根据所需列的值更新列 "Integer Key" 的值
例如当所需的列值是 "column2" 时,列 "IntegerKey" 值 = 1
当所需的列值是 "column1" 时,列 "IntegerKey" 值 = 2
当所需的列值是 "column4" 时,列 "IntegerKey" 值 = 3
datarows[] arrROWS = Datatable.Select(string.empty, "IntegerKey desc")
我有一个包含如下列的数据表:
Field1 | val 1 | val 2 | val 3
Field2 | val 1 | val 2 | val 3
Field3 | val 1 | val 2 | val 3
Field4 | val 1 | val 2 | val 3
等等..一直到Field20
在绑定到我页面上的网格之前完全重新排序行的最佳方法是什么。我会使用“字段”列来确定每一行的位置。
我做了研究,发现唯一的技术之一是克隆、删除、重新插入该行。
如果我必须对所有行执行此操作,因为 none 行处于正确位置,有人有好的方法吗?
这是我尝试过的:
DataTable dataTable2 = new DataTable();
DataRow[] row = dataTable1.Select("Field ='" + "Field2" +"'");
dataTable2 .Rows.InsertAt(row, 0);
您可以使用 LINQ 对 DataTable 进行排序。 LINQ 操作 (dt2) 的结果是 IEnumerable,但您仍然可以用它来绑定您的网格。
var dt = new DataTable();
dt.Columns.Add("Key", typeof(string));
dt.Columns.Add("Position", typeof(int));
dt.Rows.Add("Key1Value", 2);
dt.Rows.Add("Key2Value", 3);
dt.Rows.Add("Key3Value", 4);
dt.Rows.Add("Key4Value", 5);
dt.Rows.Add("Key5Value", 0);
dt.Rows.Add("Key6Value", 1);
var dt2 = dt.AsEnumerable().OrderBy(x => x.Field<int>("Position"));
foreach (DataRow dr in dt2)
{
Console.WriteLine("{0} {1}", dr["Key"], dr["Position"]);
}
我编辑了我的代码,使其符合您的排序顺序。我添加了一个名为 Position 的列,因此我可以根据需要对其进行排序。如果您想要不同的顺序,只需更改 Position 的值即可。
如果不想添加额外的列,可以在OrderBy方法中使用switch语句。
var dt = new DataTable();
dt.Columns.Add("Key", typeof(string));
dt.Rows.Add("Key1Value");
dt.Rows.Add("Key2Value");
dt.Rows.Add("Key3Value");
dt.Rows.Add("Key4Value");
dt.Rows.Add("Key5Value");
dt.Rows.Add("Key6Value");
var dt2 = dt.AsEnumerable().OrderBy(x =>
{
switch (x.Field<string>("Key"))
{
case "Key5Value": return 0;
case "Key6Value": return 1;
case "Key1Value": return 2;
case "Key2Value": return 3;
case "Key3Value": return 4;
case "Key4Value": return 5;
default : return -1;
}
}
);
foreach (DataRow dr in dt2)
{
Console.WriteLine(dr["Key"]);
}
基本上,OrderBy() 方法接受定义排序顺序的匿名方法。既然"Key5Value" returns 0,那么放在"Key6Value"(returns 1)之前。如果要从最大值到最小值对其进行排序,请使用 OrderByDescending() 方法。
我也编辑了你的代码。 getPosition 方法类似于我的 LINQ 代码中的 OrderBy() 方法。
using System;
using System.Data;
using System.Linq;
class Program
{
static void Main()
{
var dt = new DataTable();
dt.Columns.Add("Key", typeof(string));
dt.Rows.Add("Key1Value");
dt.Rows.Add("Key2Value");
dt.Rows.Add("Key3Value");
dt.Rows.Add("Key4Value");
dt.Rows.Add("Key5Value");
dt.Rows.Add("Key6Value");
var dt2 = dt.Clone();
foreach (DataRow dr in dt.Rows)
{
string key = dr["Key"].ToString();
var dRow = dt2.NewRow();
dRow.ItemArray = dr.ItemArray;
dt2.Rows.InsertAt(dRow, getPosition(key));
}
foreach (DataRow dr in dt2.Rows)
{
Console.WriteLine(dr["Key"]);
}
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
static int getPosition(string key)
{
switch (key)
{
case "Key5Value":
return 0;
case "Key6Value":
return 1;
case "Key1Value":
return 2;
case "Key2Value":
return 3;
case "Key3Value":
return 4;
case "Key4Value":
return 5;
default:
return -1;
}
}
}
版本 2: 我添加了一个包含键值(例如 Key1Value)和一对值的字典。对值是新的键值(例如键 1 值)和位置。我使用字典的原因是为了替换 switch-case 表达式。如果你愿意,你可以增加额外的价值。只需向元组添加更多类型即可。
Tuple<string, int, int, bool> // holds a sequence of a string, two integers and a boolean.
这是完整的代码。
using System;
using System.Data;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
// create table
var dt = new DataTable();
dt.Columns.Add("Key", typeof(string));
dt.Columns.Add("Val1", typeof(int));
dt.Columns.Add("Val2", typeof(int));
dt.Columns.Add("Val3", typeof(int));
dt.Columns.Add("Position", typeof(int));
// populate table
dt.Rows.Add("Key1Value", 100, 200, 300);
dt.Rows.Add("Key2Value", 100, 200, 300);
dt.Rows.Add("Key3Value", 100, 200, 300);
dt.Rows.Add("Key4Value", 100, 200, 300);
dt.Rows.Add("Key5Value", 100, 200, 300);
dt.Rows.Add("Key6Value", 100, 200, 300);
// initialize dictionary
var dict = new Dictionary<string, Tuple<string, int>>() {
{ "Key1Value", new Tuple<string, int>("Key 1 Value", 2) }, // Key1Value's new value is Key 1 Value, position is 2
{ "Key2Value", new Tuple<string, int>("Key 2 Value", 3) },
{ "Key3Value", new Tuple<string, int>("Key 3 Value", 4) },
{ "Key4Value", new Tuple<string, int>("Key 4 Value", 5) },
{ "Key5Value", new Tuple<string, int>("Key 5 Value", 0) },
{ "Key6Value", new Tuple<string, int>("Key 6 Value", 1) }
};
// set position and new key value
dt.AsEnumerable()
.ToList()
.ForEach(x => {
x["Position"] = dict[x.Field<string>("Key")].Item2;
x["Key"] = dict[x.Field<string>("Key")].Item1; // must be the last because the dictionary key is "KeyXValue", not "Key X Value"
});
// sort by Position
var dt2 = dt.AsEnumerable().OrderBy(x => x.Field<int>("Position"));
foreach (DataRow dr in dt2)
{
Console.WriteLine("{0}, {1}, {2}, {3}, {4}", dr["Key"], dr["Val1"], dr["Val2"], dr["Val3"], dr["Position"]);
}
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
由于时间因素,这是我能想到的最佳解决方案。如果您觉得可以用更好的方式完成,请发表评论。
此技术涉及创建源数据表的克隆。然后循环遍历源数据表并按所需顺序将行重新添加到 datatable2。
// Make a clone of the source datatable
DataTable dataTable2 = dataTable1.Clone();
// Loop through each row in the source datatable and check for key
foreach (DataRow dr in dataTable1.Rows)
{
string key = dr["Key"].ToString();
DataRow dRow = dataTable2.NewRow();
switch (key)
{
case "Key5Value":
// Rename actual key value if needed
dr["Key"] = "Key Rename if needed";
// Set new datarow item array to current row in loop item array
dRow.ItemArray = dr.ItemArray;
// Add datarow to desired position in dataTable 2
dataTable2.Rows.InsertAt(dRow, 0);
break;
case "Key6Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 1);
break;
case "Key1Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 2);
break;
case "Key2Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 3);
break;
case "Key4Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 4);
break;
case "Key3Value":
dr["Key"] = "Key Rename if needed";
dRow.ItemArray = dr.ItemArray;
dataTable2.Rows.InsertAt(dRow, 5);
break;
}
}
另一种解决方案可能是:
- 在数据 table 中添加一个新列 "IntegerKey"。
- 根据所需列的值更新列 "Integer Key" 的值 例如当所需的列值是 "column2" 时,列 "IntegerKey" 值 = 1 当所需的列值是 "column1" 时,列 "IntegerKey" 值 = 2 当所需的列值是 "column4" 时,列 "IntegerKey" 值 = 3
datarows[] arrROWS = Datatable.Select(string.empty, "IntegerKey desc")