2009-05-12 7 views
2

Je cherche une bonne conception/alogrithm/modèle pour les éléments suivants:C# 2.0 Conception Question - Création d'une liste des sous-listes plus

J'ai une grande liste de tâches TODO. Chacun d'entre eux a une durée estimée. Je veux diviser la plus grande liste en plus petites sous-listes, chaque sous-liste contenant un maximum de 4 heures de travail.

Mon algorithme actuel est quelque chose comme ceci:

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

En passant l'index comme ref se sent maladroit et non OOD. Je consomme vraiment la liste TODO un peu comme un flux, donc je me demande s'il y a quelque chose de similaire que je pourrais faire, mais je suis un peu un débutant C#. Je suis également actuellement limité à C# 2.0. Des pointeurs rapides sur un bon design ici?

+0

Limité à la spécification de langage .NET 2.0 ou C# 2? –

Répondre

2

Vous pouvez farcir tout en une seule méthode:

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

Ou, en utilisant itérateurs:

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

Ah, tu m'as battu. Presque identique à ma solution! – Noldorin

+0

Juste repéré quelque chose: vous incrémentez la durée * après * vous ajoutez l'article à la liste, ce qui signifie qu'une nouvelle sous-liste ne sera créée qu'une fois que la durée de l'actuelle * a dépassé * 4 heures, ce qui n'est pas tout à fait demandeur veut. – Noldorin

0

Cela devrait faire le travail:

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 simplifierait probablement des choses, mais puisque vous utilisez C# 2.0 (et probablement aussi .NET 2.0 je suppose), cela semblerait être la solution la plus simple sur.

0

Je suggère de l'encapsuler dans une classe.

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

Cela permet de fournir un prédicat pour contrôler la construction des sous-listes. Ensuite, vous pouvez simplement obtenir vos résultats.

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

Ou peut-être de cette façon.

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

Voici ma solution:

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

Notez que ce n'est pas la solution optimale ... qui irait à un nouveau niveau entier :)

En outre, cette solution distribuer les éléments un peu mieux que Noldorin et Anton solutions. Vous pourriez finir par avoir moins de listes.

Questions connexes