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

时间:2013-06-06 20:40:43

标签: c# asp.net linq

让我们看看你是否可以帮助我。我不是很擅长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();
    }                    
}

您对如何优化它有什么想法吗?

非常感谢您的关注。任何想法都将非常受欢迎(我的非母语英语也会受到更正)。

2 个答案:

答案 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())
{
    // ...
}