【问题标题】:C# 2.0 Design Question - Creating sublists from a larger listC# 2.0 设计问题 - 从更大的列表创建子列表
【发布时间】:2009-05-12 10:22:25
【问题描述】:

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

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

我目前的算法是这样的:

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

将索引作为 ref 传入感觉很尴尬,而不是 OOD。我真的像流一样消耗 TODO 列表,所以我想知道是否有类似的事情我可以做,但我有点 C# 新手。我目前也仅限于 C# 2.0。这里有关于好的设计的快速指示吗?

【问题讨论】:

  • 仅限于 .NET 2.0 或 C# 语言规范 2?

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


【解决方案1】:

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

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;
}

【讨论】:

  • 啊,你打败了我。几乎与我的解决方案相同!
  • 刚刚发现了一些东西:你增加了持续时间你将项目添加到列表中,这意味着一个新的子列表只会在当前的持续时间有超过 4 小时,这不是提问者想要的。
【解决方案2】:

这应该可以完成工作:

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),这似乎是最直接的解决方案。

【讨论】:

    【解决方案3】:

    我建议将其封装到一个类中。

    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);
    }
    

    【讨论】:

      【解决方案4】:

      这是我的解决方案:

          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 解决方案更好地分配项目。您最终可能会得到更少的列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-24
        • 1970-01-01
        相关资源
        最近更新 更多