根据其中一个字段重新排序数据表的所有行

本文关键字:排序 数据表 新排序 字段 一个 | 更新日期: 2023-09-27 18:04:58

我有一个包含如下列的DataTable:

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

在绑定到页面上的网格之前,完全重新排序行的最佳方法是什么?我将使用Field列来确定每行应该放在哪里。

我做了研究,发现唯一的技术之一是克隆,删除,重新插入行,它应该去。

如果我必须为所有行做这个,因为没有行在他们的正确位置有人有一个好的方法来做吗?

这是我尝试的:

    DataTable dataTable2 = new DataTable();
    DataRow[] row = dataTable1.Select("Field ='" + "Field2" +"'");
    dataTable2 .Rows.InsertAt(row, 0);

根据其中一个字段重新排序数据表的所有行

您可以使用LINQ对数据表进行排序。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的列,这样我就可以对它进行排序。如果你想要不同的顺序,只需改变位置的值。

如果您不想添加额外的列,您可以在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"返回0,那么它被放在"Key6Value"(返回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值)和位置。我使用字典的原因是替换切换大小写表达式。如果你愿意,你可以添加额外的值。只需在元组中添加更多类型。

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

另一个解决方案是:

  1. 在数据表中增加一个新列"IntegerKey"。
  2. 根据所需列的值更新列"Integer Key"的值例如,当所需的列值是说"column2",然后列"IntegerKey"值= 1当所需的列值是说"column1",然后列"IntegerKey"值= 2当所需列值为"column4"时,列"IntegerKey"值= 3
  3. datarows[] arrROWS = Datatable.Select(string.empty, "IntegerKey desc")