对不重复的实体列表的所有属性执行 LINQ 搜索
Performing a LINQ search on all properties of a list of entities without duplicates
我需要对数据集执行 LINQ 搜索,以查找搜索键与所有列中存在的所有值匹配的所有数据行。例如,我在数据网格中有一个这样的数据集:
Province Code Region
==================================
Alessandria AL Piemonte
Aosta AO Valle d'Aosta
Varese VA Lombardia
在代码中表示为 List<Province> tableData
,搜索关键字存储在 param.Search.Value
中。在下面的代码中,我过滤了网格的所有可搜索列并在 tableData
上执行搜索
if (param.Search != null && !string.IsNullOrEmpty(param.Search.Value))
{
var columns = param.Columns.GetAllSearchableColumns();
searchedData.AddRange(param.SelectMatchingData(tableData, columns));
}
我使用两个扩展来执行搜索:
public static IEnumerable<T> SelectMatchingData<T>(this IDataTablesRequest param, IEnumerable<T> tableData, List<Column> columns)
{
return tableData.SelectMany(entity => columns, (entity, column) => new { entity, column })
.Select(@t => new { @t, isMatch = @t.entity.GetMatchingValue(@t.column.Name, param.Search.Value) })
.Where(@t => @t.isMatch)
.Select(@t => @t.@t.entity);
}
public static bool GetMatchingValue(this object src, string propertyName, string valueToMatch)
{
if (src == null)
{
return false;
}
var propertyValue = src.GetType().GetProperty(propertyName).GetValue(src, null).ToString();
return propertyValue.Trim().ToLower().StartsWith(valueToMatch.Trim().ToLower());
}
当我使用 'va' 作为搜索关键字时,结果将是:
Province Code Region
==================================
Aosta AO Valle d'Aosta
Varese VA Lombardia
Varese VA Lombardia
因为 Varese 行在值 Varese 和 VA 上匹配。
如何改进我的 LINQ 代码以避免重复?
您可以使用 Distinct()
删除重复项。然而,尽管这样做会 "solve" 问题,但它会掩盖算法的问题:最好不要首先添加重复项,而不是事后消除它们。
您可以更改 SelectMatchingData
以在 Any()
条件下扩展列,避免重复检查:
public static IEnumerable<T> SelectMatchingData<T>(this IDataTablesRequest param, IEnumerable<T> tableData, List<Column> columns) {
return tableData
.Where(entity => columns.Any(column => entity.GetMatchingValue(column.Name, param.Search.Value)));
}
我需要对数据集执行 LINQ 搜索,以查找搜索键与所有列中存在的所有值匹配的所有数据行。例如,我在数据网格中有一个这样的数据集:
Province Code Region
==================================
Alessandria AL Piemonte
Aosta AO Valle d'Aosta
Varese VA Lombardia
在代码中表示为 List<Province> tableData
,搜索关键字存储在 param.Search.Value
中。在下面的代码中,我过滤了网格的所有可搜索列并在 tableData
if (param.Search != null && !string.IsNullOrEmpty(param.Search.Value))
{
var columns = param.Columns.GetAllSearchableColumns();
searchedData.AddRange(param.SelectMatchingData(tableData, columns));
}
我使用两个扩展来执行搜索:
public static IEnumerable<T> SelectMatchingData<T>(this IDataTablesRequest param, IEnumerable<T> tableData, List<Column> columns)
{
return tableData.SelectMany(entity => columns, (entity, column) => new { entity, column })
.Select(@t => new { @t, isMatch = @t.entity.GetMatchingValue(@t.column.Name, param.Search.Value) })
.Where(@t => @t.isMatch)
.Select(@t => @t.@t.entity);
}
public static bool GetMatchingValue(this object src, string propertyName, string valueToMatch)
{
if (src == null)
{
return false;
}
var propertyValue = src.GetType().GetProperty(propertyName).GetValue(src, null).ToString();
return propertyValue.Trim().ToLower().StartsWith(valueToMatch.Trim().ToLower());
}
当我使用 'va' 作为搜索关键字时,结果将是:
Province Code Region
==================================
Aosta AO Valle d'Aosta
Varese VA Lombardia
Varese VA Lombardia
因为 Varese 行在值 Varese 和 VA 上匹配。
如何改进我的 LINQ 代码以避免重复?
您可以使用 Distinct()
删除重复项。然而,尽管这样做会 "solve" 问题,但它会掩盖算法的问题:最好不要首先添加重复项,而不是事后消除它们。
您可以更改 SelectMatchingData
以在 Any()
条件下扩展列,避免重复检查:
public static IEnumerable<T> SelectMatchingData<T>(this IDataTablesRequest param, IEnumerable<T> tableData, List<Column> columns) {
return tableData
.Where(entity => columns.Any(column => entity.GetMatchingValue(column.Name, param.Search.Value)));
}