我有以下Tuples
列表,我填写了标题/列名称,后面跟着可以在该列中找到的值列表。然后我想用整个列表查询DataTable
。
List<Tuple<string, IEnumerable<string>>> filters = new List<Tuple<string, IEnumerable<string>>>();
现在我正在执行以下操作,将每个作为单独的查询运行,在循环中逐个过滤。但我相信应该有一种方法可以做到这一点,而无需循环和运行多个查询。即立即将所有查询一起应用。
var dataTemp = MyDataTable.AsEnumerable();
foreach (var filter in filters)
{
datTemp = datTemp.Where(row => filter.Item2.Contains(row.Field<String>(filter.Item1)));
}
return dataTemp;
答案 0 :(得分:1)
您应该能够针对所有过滤器测试每一行:
var dataTemp = MyDataTable.AsEnumerable()
.Where(row => filters.All(filter => filter.Item2.Contains(row.Field<string>(filter.Item1))));
根据过滤器IEnumerable<string>
的性质,您可能希望转换过滤器以加快处理速度:
var fastFilters = filters.Select(f => (f.Item1, new HashSet<string>(f.Item2)));
var dataTemp = MyDataTable.AsEnumerable()
.Where(row => fastFilters.All(filter => filter.Item2.Contains(row.Field<string>(filter.Item1))));
我通常使用扩展程序将IEnumerable<>
转换为HashSet
:
public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source) => new HashSet<T>(source);
然后你可以
var fastFilters = filters.Select(f => (f.Item1, f.Item2.ToHashSet()));
答案 1 :(得分:0)
这是linq查询:
filters.Aggregate(dataTemp,
(current, filter) => current.Where(row => filter.Item2.Contains(row.Field<string>(filter.Item1))));
您还可以实现扩展方法:
public static EnumerableRowCollection<DataRow> CustomFilter(this DataTable @this,
IEnumerable<Tuple<string, IEnumerable<string>>> filters)
{
var dataTemp = @this.AsEnumerable();
return filters.Aggregate(dataTemp,
(current, filter) => current.Where(row => filter.Item2.Contains(row.Field<string>(filter.Item1))));
}