我有一个 Row 对象,其中包含存储在 RowValue 对象中的值(列)列表。我想根据标记为第一个的列的值对此列表进行排序。
RowValue 对象具有一个名为"key"的属性,该属性是包含验证规则的列对象。它有另一个名为"value"的属性,它是列的字符串或数值。
列验证规则还包含一个名为"display_order"的属性,该属性告诉我在网格中显示列的顺序。
我想根据第一列的值按升序对我的列表进行排序。基本上,我想对具有最小"display_order"值的列的值进行排序。
行对象:
public class Row
{
public List<RowValue> Values { get; set; } = new List<RowValue>();
}
行值:
public class RowValue
{
public Column key { get; set; }
public string value { get; set; }
}
列:
public class Column
{
public string name;
public ColumnValidation ColumnValidation;
}
最后,列验证:
public class ColumnValidation
{
public string column_label;
public DataTypeEnum data_type;
public int width;
public int decimal_places;
public int display_order;
public string calculation_formula;
public string edit_style;
public string default_value;
public decimal? minimum_value;
public decimal? maximum_value;
public bool is_column_nullable = false;
public bool inherit_values = false;
public bool display_column = false;
public bool is_editable = false;
public int column_style;
public string code_table_name;
public string code_display_name;
public string code_data_column_name;
}
我正在尝试用这样的东西重新排序我的行,但它似乎不起作用:
// reorder rows
// get the column definition for the first column
Column firstColumn = rows.Select(x => x.Values).FirstOrDefault().OrderBy(x => x.key.ColumnValidation.display_order).Select(x => x.key).FirstOrDefault();
rows = rows.OrderBy(x => x.Values.OrderBy(y => y.key.ColumnValidation.display_order).FirstOrDefault().value).ToList();
所以每个Row
都有零个或多个RowValues
。每个RowValue
都有一个Column
和一个Value
。每个Column
都有一个DisplayOrder
对于每一行,您希望显示顺序最低的列的值。然后按这些值排序。
IEnumerable<Row> rows = ...
var result = rows.Select(row => new
{
OriginalRow = row,
// every row has zero or more Values
// every RowValue has a Key.ColumnValidation.DisplayOrder
// Order the RowValues by Key.ColumnValidation.DisplayOrder
SortValue = row.Values
.Orderby(rowValue => rowValue.Key.ColumnValidation.DisplayOrder)
// from this sorted sequence of RowValues, select the Value
.Select(rowValue => rowValue.Value)
// and keep only the first one, which is the one of the first displayed column
.FirstOrDefault(),
})
所以现在你有一个项目序列,其中每个项目都包含一个OriginalRow
和一个SortValue
。SortValue 是具有最低列显示顺序的 RowValue 的值。
继续 LINQ:
.OrderBy(selectResult => selectResult.SortedValue)
如果您只需要原始行:
.Select(orderedSelectResult => orderedSelectResult.OriginalValue);
假设您打算按Row.Values
列表的最低display_order
对List<Row>
进行排序,并且您不需要就地排序,并且每个Row.Values
都具有相同的最低display_order
值,或者可以针对每个Row
可用的最低值进行排序,则可以使用 LINQ:
var ans = rs.OrderBy(r => r.Values.OrderBy(rv => rv.key.ColumnValidation.display_order)
.First()
.value)
.ToList();
据我了解,您有一个行列表,每个行都包含一个带有值的列列表。 这些列具有基于其显示顺序的固有排序键。
然后,对于给定的结果集,您希望找到排序顺序最低的列,然后使用该列按该列对所有行对象进行排序。
我整理了一些代码。 我把它放在一个.NET Fiddle中,这样你就可以试验它了。 尝试更改排序顺序键,看看它是否与您的请求匹配。
以下是代码的关键部分:
// find column with lowest sort value that is actually present
// get flat list of all values across rows
var firstColumnLabel = rows.SelectMany(l => l.Values)
// get validation column
.Select(v => v.key.ColumnValidation)
// get label of first column
.OrderBy(v => v.display_order)
.Select(v => v.column_label)
.FirstOrDefault();
// sort rows by this column
// if a row lacks the column, then it gets bumped to the end
var sortedRows = rows
.Select(r => new { r, key = GetSortKey(r, firstColumnLabel) })
// push rows with missing columns to end
.OrderBy(rr => rr.key == null ? 1 : 0)
// now do a secondary sort by the actual key
.ThenBy(rr => rr.key)
// recover original row object without sort key
.Select(rr => rr.r);
// ...
static string GetSortKey(Row r, string column_label) {
var columns = r.Values;
var colForLabel = columns.FirstOrDefault(c => c.key.ColumnValidation.column_label == column_label);
if(colForLabel != null) {
return colForLabel.value;
}
return null;
}
以下是完整的代码:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
// some sample data with row values and column validation orders
var sampleRow1 = new (string value, int column_order, string column_label)[] {
("Val 1", 2, "Column B"),
("Val 2", 1, "Column A"),
("Val 30", 5, "Column E")
};
var sampleRow2 = new (string value, int column_order, string column_label)[] {
("Val 1", 2, "Column B"),
("Val 2", 5, "Column E")
};
var sampleRows = new[] { sampleRow1, sampleRow2 };
// build up the row data
var rows = new List<Row>();
foreach(var sampleRow in sampleRows) {
var row = new Row();
rows.Add(row);
row.Values = new List<RowValue>();
foreach(var sampleColumn in sampleRow) {
row.Values.Add(new RowValue {
value = sampleColumn.value,
key = new Column {
ColumnValidation = new ColumnValidation
{
display_order = sampleColumn.column_order,
column_label = sampleColumn.column_label
}
}
});
} // END: build columns in Row
} // END: build list of Row objects
// find column with lowest sort value that is actually present
// get flat list of all values across rows
var firstColumnLabel = rows.SelectMany(l => l.Values)
// get validation column
.Select(v => v.key.ColumnValidation)
// get label of first column
.OrderBy(v => v.display_order)
.Select(v => v.column_label)
.FirstOrDefault();
// sort rows by this column
// if a row lacks the column, then it gets bumped to the end
var sortedRows = rows
.Select(r => new { r, key = GetSortKey(r, firstColumnLabel) })
// push rows with missing columns to end
.OrderBy(rr => rr.key == null ? 1 : 0)
// now do a secondary sort by the actual key
.ThenBy(rr => rr.key)
// recover original row object without sort key
.Select(rr => rr.r);
Console.WriteLine($"We sorted by {firstColumnLabel}");
foreach(var srow in sortedRows) {
Console.WriteLine("Row");
foreach(var col in srow.Values) {
Console.WriteLine($"{col.key.ColumnValidation.column_label} = {col.value}");
}
}
}
static string GetSortKey(Row r, string column_label) {
var columns = r.Values;
var colForLabel = columns.FirstOrDefault(c => c.key.ColumnValidation.column_label == column_label);
if(colForLabel != null) {
return colForLabel.value;
}
return null;
}
}
public class Row
{
public List<RowValue> Values { get; set; }
}
public class RowValue
{
public Column key { get; set; }
public string value { get; set; }
}
public class Column
{
public ColumnValidation ColumnValidation;
}
public class ColumnValidation
{
public string column_label;
public int display_order;
// ...
}