4 Stimmen

LINQ: Wie verwendet man RemoveAll ohne For-Schleife mit Array

Ich habe derzeit ein Log-Objekt, das ich möchte Objekte aus, basierend auf einer LINQ-Abfrage zu entfernen. Ich möchte alle Datensätze im Protokoll entfernen, wenn die Summe der Versionen innerhalb eines Programms größer als 60 ist. Derzeit bin ich ziemlich zuversichtlich, dass dies funktionieren wird, aber es scheint kludgy:

        for (int index = 0; index < 4; index++)
        {
          Log.RemoveAll(log =>
                    (log.Program[index].Version[0].Value +
                     log.Program[index].Version[1].Value +
                     log.Program[index].Version[2].Value ) > 60);
        }

Das Programm ist ein Array mit 4 Werten und die Version hat ein Array mit 3 Werten. Gibt es eine einfachere Möglichkeit, diese RemoveAll in LINQ zu tun, ohne die for-Schleife zu verwenden?

Vielen Dank für jede Hilfe im Voraus!


EDIT : Leider ist der Typ der Variablen, die Programm und Version basieren auf (das ist eine Einschränkung des Rahmens, in dem ich arbeite) schränkt uns so, dass ich nicht auf die "Any" Mitglied zugreifen können. Ich habe jedoch bestätigt, dass die Lösung von tzaman funktioniert, wenn Sie Folgendes haben Listen indem ich einen Beispielcode erstelle. Ich bin auf Array-ähnliche Variablen beschränkt (siehe die auskommentierten Bereiche)

// I'm restricted to Arrays, but if I had lists, this would work. 
  internal class MyLogCollection
  {
    List<MyLog> MyListOfZones = new List<MyLog>();

    public void TestRemove()
    {
      // Original Implementation
      for (int i = 0; i < 4; i++)
      {
        MyListOfZones.RemoveAll(log => (log.MyZoneArray[0].MyVersionArray[0].Value +
                                        log.MyZoneArray[0].MyVersionArray[1].Value +
                                        log.MyZoneArray[0].MyVersionArray[2].Value) > 60);
        //"Any" method is not available off of intellisense scope on MyZoneArray 
      }

      // Better Implementation (thanks tzaman!)
      MyListOfZones.RemoveAll(log => (log.MyZoneArray.Any(prog =>
                                                          prog.MyVersionArray.Sum(ver => ver.Value) > 60)));
    }
  }
  internal class MyLog
  {
    //public MyZone[] MyZoneArray = new MyZone[4];

    public List<MyZone> MyZoneArray = new List<MyZone>(4);

  }
  internal class MyZone
  {
    //public MyVersion[] MyVersionArray = new MyVersion[3];
    public List<MyVersion> MyVersionArray = new List<MyVersion>(3);
  }
  internal class MyVersion
  {
    public byte Value { get; set;}

  }

Danke tzaman!

8voto

tzaman Punkte 44506

Das sollte reichen, denke ich:

Log.RemoveAll(log => 
              log.Program.Any(prog => 
                              prog.Version.Sum(ver => ver.Value) > 60));

EDIT : Okay, so fügen wir Erweiterungsmethoden hinzu, um IEnumerable s aus Ihren indizierbaren "array-ähnlichen" Objekten, so dass Sie LINQ auf sie anwenden können:

static class MyExtensions
{
    public static IEnumerable<MyZone> Enumerate(this MyZoneArray zone)
    {
        for (int i = 0; i < zone.Length; i++)
            yield return zone[i];
    }

    public static IEnumerable<MyVersion> Enumerate(this MyVersionArray version)
    {
        for (int i = 0; i < version.Length; i++)
            yield return version[i]
    }
}

Ich nehme an, dass die MyZoneArray y MyVersionArray Typen haben eine Length Feld, aber wenn nicht, können Sie einfach 4 y 3 dort drüben. Damit können Sie nun die Enumerate() Funktion auf das Sammelobjekt, um eine IEnumerable Version der Sammlung, mit allen damit verbundenen LINQy-Vorteilen: log.MyZoneArray.Enumerate().Any( ... )

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X