根据其他列表上的索引从表中选择行

本文关键字:选择 索引 其他 列表 | 更新日期: 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())
{
    // ...
}