从IEnumerable中删除已使用的元素

时间:2016-09-27 09:10:37

标签: c# algorithm loops

我有一组看起来像这样的数据

| title | network | start |  end  | type |
------------------------------------------
| FOO   |    1    | 02:00 | 05:00 |   1  |
| FOO   |    1    | 02:00 | 03:10 |   2  |
| FOO   |    1    | 03:11 | 04:00 |   2  |
| FOO   |    1    | 04:01 | 05:00 |   3  |
| BAR   |    1    | 05:01 | 07:00 |   3  |

这里是类型

的解释
  • 类型1是container
  • 类型2是partial
  • 类型3是single

您必须知道container包含所有部分内容,如果标题相同,则可能包含single

IEnumerable<Item> GetPartials(Item container, IEnumerable<Item> collection)
{
    foreach(Item item in collection)
    {
        if(container.Network == item.Network
            && container.Title == item.Title)
            // there is obviously also a check on the times, but it's long to write
        {
            yield return item;
        }
    }
}

现在,我需要将部分聚合到容器中并将其删除。

考虑到我有一个像这样的方法

public Item Aggregate(Item container, IEnumerable<Item> partials)
{
    ... //this is irrelevant
    return container;
}

如果Item像这样

,我会循环收集集合
public IEnumerable<Item> FilterAndAggregate(IEnumerable<Item> collection)
{
    foreach(Item item in collection)
    {
        if(item.Type == 1)
        {
            yield return Aggregate(item, GetPartials(item, collection));
        }
        else if (item.Type == 3)
        {
            yield return item;
        }
        // I'm filtering the partials because I already aggregated them
    }
}

但正如您在上一个循环中看到的那样,我可能yield也是我已经聚合的single

如何从collection

中排除部分内容

1 个答案:

答案 0 :(得分:1)

假设Item类像这样

public class Item
{
    public string Title { get; set; }
    public int Network { get; set; }
    public string Start { get; set; }
    public string End { get; set; }
    public int Type { get; set; }

    public List<Item> Partials { get; set; }
}

这是代码。

    IEnumerable<Item> GetPartials(Item container, List<Item> collection)
    {
        for (int i = collection.Count - 1; i >= 0; i--)
        {
            if (container.Network == collection[i].Network
                && container.Title == collection[i].Title)
            // there is obviously also a check on the times, but it's long to write
            {
                yield return collection[i];
                collection.RemoveAt(i);//remove already checked item
            }
        }
    }

    public Item Aggregate(Item container, IEnumerable<Item> partials)
    {
        //this is irrelevant
        container.Partials = partials.ToList();
        return container;
    }

    public IEnumerable<Item> FilterAndAggregate(IEnumerable<Item> collection)
    {
        var col = collection as IList<Item> ?? collection.ToList();
        var partials = col.Where(x => x.Type == 2).ToList();
        var notPartials = col.Where(x => x.Type != 2).ToList();
        foreach (Item item in notPartials)
        {
            if (item.Type == 1)
            {
                yield return Aggregate(item, GetPartials(item, partials));
            }
            else if (item.Type == 3)
            {
                yield return item;
            }
            // I'm filtering the partials because I already aggregated them
        }
    }

如果有大量记录,它会运行得更好。