定制需要索引的DataTable

时间:2019-06-12 11:18:53

标签: c# linq datatable

正如标题所述,我需要为DataTable进行自定义排序,在其中使用DataRow的索引,结果应为EnumerableRowCollection或OrderedEnumerableRowCollection,因为我需要一个表(默认顺序)和一个DataView(自定义顺序)。

我想要的顺序:首先按几列排序(例如,姓名,姓氏...)。然后将表拆分为table1和table2(仅是表的一半)。然后从第一张表和第二张表中交替选择。结果应该是

第1行表格
table2的行
table1的行

原始表不应受到影响,其结果应该是对原始表的引用。

internal static DataView GetSortedView(this DataTable table)
{
    return table.GetSortedTable().AsDataView();
}

internal static void OrderedEnumerableRowCollection<DataRow> GetSortedTable(this DataTable table)
{

int half = table.Rows.Count / 2;
//sort columns by name for example
var enumerable = table.AsEnumerable().OrderBy(field => field.Field<string>("Name"), new NaturalStringComparer());

//here is the tricky part
enumerable= enumerable.OrderBy(row =>
                    {
                        int myIndex = ?; //I cannot use table.Rows.IndexOf(row) because the order of the current OrderedEnumerableRowCollection should be used and not the default order of the table

                        bool upperHalf = myIndex > half;
                        if (upperHalf)
                        {
                            myIndex -= half;
                        }

                        return new CustomSortItem(myIndex , upperHalf);
                    }, new CustomSort());
return enumerable;
}

我尝试先为索引添加一个新列,但这并没有真正起作用,因为当我尝试删除该列时,最后,由于延迟加载,我收到了一个异常。

internal static void OrderedEnumerableRowCollection<DataRow> GetSortedTable(this DataTable table)
{

//create another column for an index
string tempSortName = "[TEMP_SORT]";
table.Columns.Add(tempSortName);

//sort columns by Name for example
var enumerable= table.AsEnumerable().OrderBy(field => field.Field<string>("Name"), new NaturalStringComparer());

//set the temporary order (index)
int count = 0;
foreach(DataRow row in enumerable)
{
    row[tempSortName] = count++;
}

//here is the tricky part
int half = table.Rows.Count / 2;
enumerable= enumerable.OrderBy(row =>
                    {
                        int myIndex = int.parse(row[tempSortName].ToString()); //exception here. column not found

                        bool upperHalf = myIndex  > half;
                        if (upperHalf)
                        {
                            myIndex  -= half;
                        }

                        return new CustomSortItem(myIndex , upperHalf);
                    }, new CustomSort());

                    table.Columns.Remove(tempSortName);
return enumerable;
}

我也不想使用IEnumerable,因为当我创建一个DataView时,我必须创建另一个表以创建一个表,然后引用丢失(view.Table不是原始表,而只是没有复制的表)。参考)。

IEnumerable<DataRow> enumerable...
enumerable.CopyToDataTable().AsDataView();
// I have to call CopyToDataTable() in order to create a DataView

2 个答案:

答案 0 :(得分:0)

如果您使用Select的两个参数版本按顺序对行进行计数?

enumerable = enumerable.Select((r, i) => new { r, i })
                       .OrderBy(ri => {
                            var upperHalf = ri.i > half;
                            var myIndex = ri.i - (upperHalf ? half : 0);
                            return new CustomSortItem(myIndex, upperHalf);
                        }, new CustomSort());

答案 1 :(得分:0)

一段时间后,我找到了一个解决方案,而GetSortedTableGetSortedView的解决方案是不同的(每个都有自己的解决方案)。如果有人有更好的解决方案,我将不胜感激。

internal static void DataView GetSortedView(this DataTable table)
{

   //create another column for an index
   string tempSortName = "[TEMP_SORT]";
   table.Columns.Add(tempSortName);

   //sort columns by Name for example
   var enumerable= table.AsEnumerable().OrderBy(field => field.Field<string>("Name"), new NaturalStringComparer());

   //set the temporary order (index)
   int count = 0;
   foreach(DataRow row in enumerable)
   {
       row[tempSortName] = count++;
   }

   //here is the tricky part
   int half = table.Rows.Count / 2;
   enumerable= enumerable.OrderBy(row =>
    {

      if (int.TryParse(row[tempSortName]?.ToString(), out int myIndex )) //everything here is triggered if row[tempSortName] is set... or before it is set... idk... wtf. so there is a new column but there are not any indices in it (or just one)
       {
         myIndex++;
         bool upperHalf = myIndex  > half;
         if (upperHalf)
         {
            myIndex  -= half;
         }
         return new CustomSortItem(myIndex , upperHalf);
       }
    }, new CustomSort());

   DataView view = enumerable.AsDataView();
   view.Table.Columns.Remove(tempSortName);

   return view;
}


internal static IEnumerable<DataRow> GetSortedTable(this DataTable table)
{
   IEnumerable<DataRow> result;
   //sort columns by Name for example
   var enumerable= table.AsEnumerable().OrderBy(field => field.Field<string>("Name"), new NaturalStringComparer());
   int half =  table.Rows.Count / 2;
   IEnumerable<DataRow> one = enumerable.Take(half);
   IEnumerable<DataRow> two = enumerable.Skip(half);
   result = one.InterleaveEnumerationsOfEqualLength(two);
   return result;
 }

internal static IEnumerable<DataRow> InterleaveEnumerationsOfEqualLength<DataRow>(this IEnumerable<DataRow> first, IEnumerable<DataRow> second)
{
   using (IEnumerator<DataRow> enumerator1 = first.GetEnumerator(), enumerator2 = second.GetEnumerator())
   {
      while (enumerator1.MoveNext() && enumerator2.MoveNext())
      {
         yield return enumerator1.Current;
         yield return enumerator2.Current;
      }
    }
}