拆分对象列表

时间:2014-07-22 12:36:26

标签: c# .net ienumerable

所以,这是我的代码:

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方法?

更新:按日期排序的所有行和期间,所有行始终处于其中一个期间。

3 个答案:

答案 0 :(得分:2)

更快的方法是在两个结构上执行连接,但Linq仅支持等连接(两个表达式相等的连接)。在您的情况下,您正在加入一个值范围值的值,因此无法进行等连接。

在开始优化之前,请确保需要进行优化。如果此功能更快,您的程序会明显更快吗?您在这个功能中花了多少时间?

如果优化不会使整个整体计划受益,那么请不要担心 - 确保它有效,然后专注于该计划的其他功能。

那就是说,因为你说行和句点已经按日期排序了,你可以通过使用循环,循环遍历行直到你超出当前时期,然后转移到下一行来获得一些性能优势期。至少,您不会多次枚举rows(或periods)。

答案 1 :(得分:1)

您的代码中存在一些问题:rowsIEnumerable,因此可以多次枚举它。在foreach。将它更改为更稳定的东西是个好主意,比如数组,在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();

答案 2 :(得分:-1)

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

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

无论如何,这更像是一个总体思路,实施很重要。如果 n m 非常小,您可能无法获得任何好处,但如果它们很大(巨大),我可以打赌Split方法会更快地运行

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