2009-05-12 13 views
2

ich suche ein gutes Design/alogrithm/Muster für den folgenden:C# 2.0 Design-Frage - Erstellen von Unterlisten aus einer größeren Liste

Ich habe eine große Liste von TODO Aufgaben. Jeder von ihnen hat eine geschätzte Dauer. Ich möchte die größere Liste in kleinere Unterlisten aufteilen, wobei jede Unterliste maximal 4 Stunden Arbeit enthält.

Mein aktueller Algorithmus ist so etwas wie folgt aus:

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

Vorbei an der Index in als ref fühlt sich unangenehm und nicht OOD. Ich verzehre wirklich die TODO-Liste etwas wie ein Strom, also frage ich mich, ob es etwas Ähnliches gibt, das ich tun könnte, aber ich bin ein gewisser C# Neuling. Ich bin derzeit auch auf C# 2.0 beschränkt. Irgendwelche schnellen Hinweise auf ein gutes Design hier?

+0

Begrenzt auf .NET 2.0 oder C# -Sprachspezifikation 2? –

Antwort

2

Sie können alles in einem Verfahren stopfen:

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

Oder Iteratoren mit:

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

Ahh, du hast mich dazu geschlagen. Fast identisch mit meiner Lösung! – Noldorin

+0

Nur etwas entdeckt: Sie erhöhen die Dauer * nachdem * Sie das Element zur Liste hinzufügen, was bedeutet, dass eine neue Unterliste erst erstellt wird, wenn die Dauer des aktuellen * 4 Stunden überschritten hat, was nicht ganz das ist Fragesteller will. – Noldorin

0

Das die Arbeit machen sollte:

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 die Dinge vereinfachen würde wahrscheinlich, Aber da Sie C# 2.0 verwenden (und wahrscheinlich auch .NET 2.0, würde ich annehmen), würde dies als die einfachste Lösung erscheinen auf.

0

Ich würde vorschlagen, dies in eine Klasse zu kapseln.

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

Dies ermöglicht es, ein Prädikat bereitzustellen, um zu steuern, wie die Unterlisten erstellt werden. Dann können Sie einfach Ihre Ergebnisse erhalten.

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

Oder vielleicht auf diese Weise.

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

Hier ist meine Lösung:

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

Beachten Sie, dass diese Lösung nicht die optimal ist ... das auf eine ganz neue Ebene gehen würde :)

Auch diese Lösung Verteilen Sie die Artikel ein wenig besser als Noldorin und Anton Lösungen. Sie könnten am Ende weniger Listen bekommen.

Verwandte Themen