2009-03-20 6 views
2

Disons que nous avons une liste {a, a, a, b, b, c, c}Tout Si prevValue! = Chose currValue dans une boucle

Nous voulons faire une boucle dans la liste et faire une sorte de changer lorsque la valeur de l'élément change ... par exemple:

prevEmployer = String.empty; 
foreach(Person p in PersonList){ 
    if(p.Employer != prevEmployer){ 
    doSomething(); 
    prevEmployer = p.Employer; 
    } 
    ... more code 
} 

Y at-il une alternative à cela? Ça m'a l'air cludgy. Edit: rendu le code plus réaliste au problème actuel.

Répondre

3

Cela dépend vraiment de ce que vous essayez de faire avec le reste du code. La réponse de @Marc Gravell est correcte si vous avez seulement besoin d'effectuer une action pour chaque élément distinct de la liste, cependant si doSomething() ne fait que définir un état basé sur le fait que l'élément list a changé et que vous opérez sur chaque élément la liste (ou besoin des éléments individuels pour un autre but), alors votre méthode semble parfaitement raisonnable.

+0

Je dois effectuer des actions sur chaque élément de la liste, mais besoin de réinitialiser quelque chose quand une certaine propriété de l'objet change. Je pense que le moyen simple et cludgy peut être le meilleur après tout. – cleverswine

5

Voulez-vous connaître les valeurs distinctes? C'est-à-dire qu'il y aura jamais {a, a, a, b, b, a, c, c, a}? Sinon, vous pouvez utiliser LINQ:

foreach(string s in theList.Distinct()) { 
    doSomething(); // with s 
} 

Re votre mise à jour; peut-être utiliser quelque chose comme DistinctBy:

foreach(var item in data.DistinctBy(x=>x.Foo)) { 
    Console.WriteLine(item.Bar); 
} 

public static IEnumerable<TSource> DistinctBy<TSource,TValue>(
     this IEnumerable<TSource> source, Func<TSource,TValue> selector) { 
    var set = new HashSet<TValue>(); 
    foreach (var item in source) { 
     if (set.Add(selector(item))) { 
      yield return item; 
     } 
    } 
} 
+0

Désolé, j'aurais dû clarifier - Je ne veux pas de valeurs distinctes. Ceci est un exemple très simple, je compare réellement une propriété d'un objet dans la boucle (et il est trié par cette propriété) – cleverswine

+0

Je vais échanger mon exemple pour "DistinctBy" ... –

0

me semble bon aussi longtemps que String.Empty est jamais un élément de votre liste et votre liste est triée. Peut vouloir s'assurer que theList n'est pas muté par un autre thread. Ressemble à une façon assez courante de gérer le travail sur une transition dans la liste ...

0

J'ai décidé d'opter pour la solution suivante, qui est beaucoup plus jolie mais qui entraîne plus d'appels db.

foreach(Employer employer in EmployerList){ 
    ProcessEmployees(employer); 
} 

ProcessEmployees(Employer employer){ 
    EmployeeList = GetEmployees(employer); 
    foreach(Employee employee in EmployeeList){ 
    doStuff... 
    } 
} 

Ainsi, au lieu de commencer par {a, a, a, b, b, c, c}, je vais le traitement de {a, a, a} {b, b} {c, c}

+0

Vous ne savez que vous pourriez faire avec: foreach (var employeeGroup dans EmployeeList.GroupBy (employé => employee.Employer) foreach (employé var dans employeeGroup) Les boucles foreach intérieur sur tous les employés de l'employeur employeeGroup.Key est l'employeur – Niki

+0

Je ne connaissais pas GroupBy - c'est plutôt mignon, je pense que cela résout mon problème original sans le refactoring que j'ai fini par faire, je dois l'essayer maintenant :) – cleverswine

+0

Oh, c'est un LINQ chose. Je ne suis pas prêt à lancer LINQ dans la base de code à 15 heures un vendredi. Pour référence, il existe un exemple décent sur MSDN: http://msdn.microsoft.com/en-us/library/bb534304.aspx – cleverswine