C#2.0设计问题 - 从更大的列表创建子列表

时间:2009-05-12 10:22:26

标签: c# design-patterns list .net-2.0

我正在为以下方面寻找一个好的设计/算法/模式:

我有一大堆TODO任务。他们每个人都有一个估计的持续时间。我想将较大的列表分成较小的子列表,每个子列表包含最多4小时的工作。

我目前的算法是这样的:

while( index < list.Count )
{
    List<string> subList = CreateSublist( ref index );
    SaveSubList(subList);
}

将索引作为ref传递感觉很尴尬,而不是OOD。我真的很喜欢TODO列表,有点像流,所以我想知道我能做些类似的东西,但我有点像C#新手。我目前也仅限于C#2.0。有关优秀设计的快速指示吗?

4 个答案:

答案 0 :(得分:2)

你可以用一种方法填充所有内容:

List<List<TodoTask>> GetTodoTasks(IEnumerable<TodoTask> tasks, int timeWindow)
{
    List<List<TodoTask>> allTasks = new List<List<TodoTask>>();

    List<TodoTask> tasks = new List<TodoTask>();
    int duration = 0;

    foreach(TodoTask task in tasks)
    {
        if(duration > timeWindow)
        {
            allTasks.Add(tasks);

            duration = 0;
            tasks = new List<TodoTask>();
        }

        tasks.Add(task);
        duration += task.Duration;
    }

    allTasks.Add(tasks);        
    return allTasks;
}

或者,使用迭代器:

IEnumerable<List<TodoTask>> GetTodoTasks(IEnumerable<TodoTask> tasks, int timeWindow)
{        
    List<TodoTask> tasks = new List<TodoTask>();
    int duration = 0;

    foreach(TodoTask task in tasks)
    {
        if(duration > timeWindow)
        {
            yield return tasks;

            duration = 0;
            tasks = new List<TodoTask>();
        }

        tasks.Add(task);
        duration += task.Duration;
    }

    yield return tasks;
}

答案 1 :(得分:0)

这应该做的工作:

public static List<List<Task>> SplitTaskList(List<Task> tasks)
{
    List<List<Task>> subLists = new List<List<Task>>();
    List<Task> curList = new List<Task>();
    int curDuration; // Measured in hours.

    foreach (var item in tasks)
    {
        curDuration += item.Duration;
        if (curDuration > 4)
        {
            subLists.Add(curList);
            curList = new List<Task>();
            curDuration = 0;
        }

        curList.Add(item);
    }

    subLists.Add(curList);

    return subLists;
}

LINQ可能会简化一些事情,但由于您使用的是C#2.0(我可能也认为是.NET 2.0),这似乎是最直接的解决方案。

答案 2 :(得分:0)

我建议将其封装成一个类。

SubListBuilder<WorkItem> slb = new SubListBuilder<WorkItem>(
    workItems, sublist => sublist.Sum(item => item.Duration) <= 4);

这很好地允许提供谓词来控制子列表的构建方式。然后你就可以得到你的结果了。

while (slb.HasMoreSubLists)
{
    SaveList(slb.GetNextSubList());
}

或者也许这样。

foreach (var subList in slb.GetSubLists())
{
    SaveList(subList);
}

答案 3 :(得分:0)

这是我的解决方案:

    class Task
    {
        public string Name { get; set; }
        public int Duration { get; set; }
    }

    class TaskList : List<Task>
    {
        public int Duration { get; set; }

        public void Add(Task task, int duration)
        {
            this.Add(task);
            Duration += duration;
        }
    }

    private static IList<TaskList> SplitTaskList(IList<Task> tasks, int topDuration)
    {
        IList<TaskList> subLists = new List<TaskList>();
        foreach (var task in tasks)
        {
            subLists = DistributeTask(subLists, task, topDuration);
        }
        return subLists;
    }

    private static IList<TaskList> DistributeTask(IList<TaskList> subLists, Task task, int topDuration)
    {
        if (task.Duration > topDuration)
            throw new ArgumentOutOfRangeException("task too long");

        if (subLists.Count == 0)
            subLists.Add(new TaskList());

        foreach (var subList in subLists)
        {
            if (task.Duration + subList.Duration <= topDuration)
            {
                subList.Add(task, task.Duration);
                return subLists;
            }
        }

        TaskList newList = new TaskList();
        newList.Add(task, task.Duration);
        subLists.Add(newList);
        return subLists;
    }

请注意,这不是最佳解决方案......这将达到一个全新的水平:)

此外,此解决方案将比NoldorinAnton解决方案更好地分发项目。你最终可能会减少列表。