2016-12-06 6 views
0

Ich habe eine Methode, die eine Menge von LINQ verwendet, um einige Werte in einer Liste von Tuple<string, int> festzulegen und abzugleichen.Linq Kombinieren Sie zwei Anweisungen in eine große Aussage (Optimierung)

Im Moment bin ich immer noch mit zwei foreach Schleifen ineinander verschachtelt und ich denke, es wäre möglich, sie in eine gigantische LINQ-Abfrage zu kombinieren. Ich frage mich, was wäre der beste Weg, dies mit Optimierung als eine große Bedingung zu tun.

Dies ist die Funktion ich spreche:

private async void AddLocalChangesFromPendingOperations() 
{ 
    var pendingOperations = await this.operationsStorage.GetOperationsAsync(); 
    var list = pendingOperations. 
     SelectMany(pendingOperation => 
          pendingOperation.Settings, (pendingOperation, setting) => 
          new { pendingOperation, setting }) 
     .Where(a => a.setting.Key == "selection") 
     .Select(a => new Tuple<string, int>(
              a.pendingOperation.DefinitionId, 
              Convert.ToInt32(a.setting.Value.ValueObject))) 
     .ToList(); 

    foreach (var pendingChange in list) 
    { 
     var selection = await this.selectionsStorage.GetSelectionByIdAsync(pendingChange.Item2); 
     foreach (var selectionsViewModel in this.SelectionsList.Where(a => a.Name == selection.Name)) 
     { 
      if (pendingChange.Item1 == "selection-add-animals") 
      { 
       selectionsViewModel.IsActive = true; 
      } 
      else if (pendingChange.Item1 == "selection-remove-animals") 
      { 
       selectionsViewModel.IsActive = false; 
      } 
     } 
    } 
} 

Wenn möglich Ich mag würde die letzten beiden foreaches zu optimieren, während Linq verwenden. Ich habe etwas versucht, aber ich bin fest auf Werte in der aktuellen Liste Einstellung ...

ich dies tat:

this.SelectionsList = this 
    .SelectionsList 
    .Where(a => a.Name == selection.Name) 
    .SingleOrDefault(
     a => pendingChange.Item1 == "selection-add-animals" ? a.IsActive = true : a.IsActive = false 
    ); 
+0

Können Sie nicht einfach die Methode GetSelectionByIdAsync ändern, um eine Liste von IDs zu akzeptieren, so dass Sie die erste foreach loswerden? –

Antwort

1

In LINQ dient allgemein zum Abfragen von Elementen (Language Integrated Query). Sie könnten jedoch eine Abfrage tun und dann eine foreach am Ende:

private async void AddLocalChangesFromPendingOperations() 
{ 
    var pendingOperations = await this.operationsStorage.GetOperationsAsync(); 

    (await Task.WhenAll(pendingOperations 
     .SelectMany(pendingOperation => 
          pendingOperation.Settings, (pendingOperation, setting) => 
          new { pendingOperation, setting }) 
     .Where(a => a.setting.Key == "selection") 
     .Select(a => Tuple.Create(a.pendingOperation.DefinitionId, Convert.ToInt32(a.setting.Value.ValueObject))) 
     .Select(async pendingChange => Tuple.Create(await this.selectionsStorage.GetSelectionByIdAsync(pendingChange.Item2)), pendingChange)) 
     .SelectMany(tuple => this.SelectionsList.Where(a => a.Name == tuple.Item1.Name) 
               .Select(selectionsViewModel => Tuple.Create(selectionsViewModel, tuple.Item2)) 
     .Select(tuple => Tuple.Create(tuple.Item1, tuple.Item2.Item1 == "selection-add-animals")) 
     .ToList() 
     .ForEach(tuple => tuple.Item1.IsActive = tuple.Item2); 
} 

Ob dies klarer als Ihre ursprüngliche Implementierung ist zur Diskussion (ich glaube nicht, es ist), aber es wäre ein Weg sein, es zu tun.

HINWEIS: Dies wurde direkt in den Editor eingegeben, es könnte kleinere Syntaxfehler geben.

1

Sie können wie etwas tun:

this.SelectionsList = this.SelectionsList 
    .Where(a => a.Name == selection.Name) 
    .Select(a => 
    { 
     a.IsActive = a.Name == selection.Name ? true:false; 
     return a; 
    }).ToList(); 
+1

Sie wissen, dass dies aufgrund der verzögerten Ausführung von LINQ nichts bewirkt. –

+1

Ja, sorry, Sie sollten Abfrage mit ToList() ausführen. – Johnny

Verwandte Themen