正如标题所述,我需要为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
答案 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)
一段时间后,我找到了一个解决方案,而GetSortedTable
和GetSortedView
的解决方案是不同的(每个都有自己的解决方案)。如果有人有更好的解决方案,我将不胜感激。
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;
}
}
}