让我们看看你是否可以帮助我。我不是很擅长LINQ,所以我甚至都不知道它是否可行。实际上,我认为是,但我找不到最好的方法。
我有一个具有List和DataTable的对象。此DataTable具有与列表中项目数量相同的行数,并且它们是相关的(列表中的第一项与第一行相关,第二项与第二行相关,因此它相关)。我希望能够从DataTable中选择日期范围及其相关行。我目前正在这样做,但它有一些循环和一个IndexOf,它花了我很长时间来处理。你们对我如何加快速度有任何建议吗?
这基本上是对象的结构(我简化了一下,但重要的是这里):
public class CustomObject(){
public List<DateTime> dates { get; set; }
public DataTable table { get; set; }
}
以下是我如何选择它:
private bool SelectRange(DateTime begin, DateTime end, CustomObject custom)
{
var range = from date in custom.dates
where date.CompareTo(begin) >= 0 &&
date.CompareTo(end) < 0
select date;
DataTable tmpTable = custom.table.Copy(); // I'm doing this just to copy the structure of the DataTable
tmpTable.Clear();
if (range.Count() > 0)
{
List<DataRow> rowList = new List<DataRow>();
foreach (var date in range)
{
int dateIndex = custom.dates.IndexOf(date);
rowList.Add(custom.table.Rows[dateIndex]);
}
foreach (DataRow row in rowList)
{
tmpTable.Rows.Add(row.ItemArray);
}
custom.table = tmpTable;
}
else
{
custom.table.Rows.Clear();
}
}
您对如何优化它有什么想法吗?
非常感谢您的关注。任何想法都将非常受欢迎(我的非母语英语也会受到更正)。
答案 0 :(得分:2)
如果您想简化操作,请使用.Zip()
将两个独立列表转换为单个相关列表。
var newList = custom.dates.Zip(custom.table.Rows,
(first, second) => new { Date = first, Row = second });
完成后,您可以对每个日期/行对进行简单的选择:
var reducedList = newList.Where(i => i.Date >= begin && i.Date <= end);
完成后,您可以将缩小的列表添加到数据表中。
(我没有编译或测试上面的内容)
答案 1 :(得分:1)
DataTable.Copy
复制表 + data 的结构。我假设您只想使用空表复制结构(列)(因为之后您仍然执行DataTable.Clear
)。因此,请使用DataTable.Clone
:
DataTable tmpTable = custom.table.Clone();
但是,CopyToDataTable
根本不需要它。您可以在日期列上加入两个集合,这比行索引更合适:
var rows = from dt in range
join row in custom.table.AsEnumerable()
on dt equals row.Field<DateTime>("DateColumn")
select row;
DataTable newTable = rows.CopyToDataTAble();
Why is LINQ JOIN so much faster than linking with WHERE?
如果您坚持索引链接,我将使用此查询而不是第二个索引查找:
int[] indices = custom.dates
.Select((dt, index) => new{dt,index})
.Where(x => x.dt >= begin && x.dt < end)
.Select(x => x.index)
.ToArray();
var newTable = custom.table.AsEnumerable()
.Where((row, index) => indices.Contains(index))
.CopyToDataTable();
旁注:您应使用range.Count() > 0
而不是range.Any()
。 Enumerable.Count
需要执行整个查询才能获得总计数,即使您只想知道是否至少有一个结果。因此,请尽快使用Enumerable.Any
。
if(range.Any())
{
// ...
}