按子列表中的第一个值对列表进行排序



我有一个 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_orderList<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;
// ...
}

最新更新