根据其他列表上的索引从表中选择行
本文关键字:选择 索引 其他 列表 | 更新日期: 2023-09-27 18:17:21
让我看看你能不能帮我。我不太擅长LINQ,所以我甚至不知道这是否可能。事实上,我认为它是,但我还没有找到最好的方法。
我有一个对象,它有一个列表和一个数据表。这个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();
}
}
你对如何优化这个有什么想法吗?
非常感谢您的关注。任何想法都是非常欢迎的(对我的非母语英语的更正也将是欢迎的)。
如果你想让事情更简单,使用.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);
完成后,您可以将该简化列表添加到数据表中。
(我没有编译或测试以上)
DataTable.Copy
复制表+ data的结构。我假设你想复制的结构(列)只有一个空表(因为你执行DataTable.Clear
之后)。因此使用DataTable.Clone
:
DataTable tmpTable = custom.table.Clone();
然而,对于CopyToDataTable
,您根本不需要它。您可以在date列上连接两个集合,这比row-index:
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();
为什么LINQ JOIN比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.Any()
而不是range.Count() > 0
。即使您只想知道是否至少有一个结果,Enumerable.Count
也需要执行整个查询来获得total-count。因此,使用Enumerable.Any
,它会尽快中断。
if(range.Any())
{
// ...
}