拆分对象列表

本文关键字:列表 对象 拆分 | 更新日期: 2023-09-27 18:14:00

那么,下面是我的代码:

private List<IEnumerable<Row>> Split(IEnumerable<Row> rows, 
                                     IEnumerable<DateTimePeriod> periods) 
{
    List<IEnumerable<Row>> result = new List<IEnumerable<Row>>();
    foreach (var period in periods) 
    {
        result.Add(rows.Where(row => row.Date >= period.begin && row.Date <= period.end));
    }
    return result;
}
private class DateTimePeriod 
{
    public DateTime begin { get; set; }
    public DateTime end { get; set; }
}

如您所见,这段代码不是最好的,它遍历每个周期的所有行。我需要关于如何优化此代码的建议。也许有合适的Enumerable方法?

Update:所有的行和周期按日期排序,并且所有的行总是在这些周期中的一个

拆分对象列表

更快的方法是在两个结构上执行连接,但是Linq只支持等连接(两个表达式相等的连接)。在您的示例中,您连接的是范围中的一个值,因此不可能使用等连接。

在开始优化之前,确保它需要进行优化。如果这个函数更快,你的程序会明显更快吗?你的应用有多少时间花在这个功能上?

如果优化不会使程序整体受益,那么不要担心它-确保它有效,然后关注程序的其他功能。

也就是说,既然您说行和周期已经按日期排序,那么您可以通过使用循环获得一些性能优势,循环遍历行,直到您走出当前周期,然后移动到下一个周期。至少这样你就不用多次枚举rows(或periods)了。

您的代码中有一个小问题:rowsIEnumerable,因此它可以被多次枚举。在foreach。把它改成更稳定的东西是个好主意,比如array,放在foreach:

之外
var myRows = rows as Row[] ?? rows.ToArray();
顺便说一下

。我将你的代码更改为以下代码,使用Resharper:

var myRows = rows as Row[] ?? rows.ToArray();
return periods.Select(period => myRows.Where(row => row.Date >= period.begin && row.Date <= period.end)).ToList();

优化O(n x m)算法的最佳机会是在多个连续的O(n)操作中对其进行转换。为了获得time,你必须权衡space,所以如果你基于你的一个Enumerables中的数据创建一些lookup table,可能会在这种情况下对你有所帮助。

例如,您可以构造一个int数组,它将为属于一个周期的每一天设置(每个周期都有另一个已知的硬编码)。这将是你的第一个O(n)循环。然后你做另一个O(m)循环,只检查与row.Date对应的数组位置是否为非零(然后你在硬编码的数组中查找实际值,你得到实际的Period)。

无论如何,这是一个更一般的想法和实现是重要的。如果nm非常小,您可能不会得到任何好处,但如果它们很大(很大),我可以打赌Split方法会运行得更快。

假设您使用的所有内容都已经在内存中(不涉及EF)。