2016-03-23 6 views
1

Also habe ich mehrere Listen vom Typ Tag. Das Tag hat mehrere Eigenschaften: .Epc, .AntennaPortNumber und .LastTimeSeen. Ich möchte alle Tags aus der Hauptliste nehmen und sie in 5 kleinere Listen sortieren, aber nur eine Kopie von jedem .Epc behalten und es muss das neueste .LastTimeSeen sein. Ich bin mir nicht sicher, wo ich überhaupt anfangen soll. Ich dachte, ich muss etwas mit .GroupBy tun ein paar Mal verschachtelt? Im Moment ist der Code in zwei Hauptteile aufgeteilt: wo ich neue Tags zu den Listen hinzufüge, in die sie gehören, und wo ich ein Tag entferne, das für 500ms nicht gesehen wurde. Ich habe versucht zu verhindern, dass doppelte Tags zu den 5 Unterlisten mit .Contains hinzugefügt werden, aber da sie unterschiedliche LastTimeSeen-Eigenschaften haben, hat dies nicht den gewünschten Effekt.Entfernen von Duplikaten aus einer Liste unter Beibehaltung der neuesten C#

Vielen Dank für jede Anleitung, die jemand zur Verfügung stellen könnte!

List<Tag> tags = new List<Tag>(); 
    List<Tag> listMed1 = new List<Tag>(); 
    List<Tag> listMed2 = new List<Tag>(); 
    List<Tag> listMed3 = new List<Tag>(); 
    List<Tag> listMed4 = new List<Tag>(); 
    List<Tag> listMed5 = new List<Tag>(); 
    void OnTagsReported(ImpinjReader sender, TagReport report) 
    { 
     // This event handler is called asynchronously 
     // when tag reports are available. 
     // Loop through each tag in the report 
     // and print the data. 



     //List<Tag> tags = new List<Tag>(); 
     foreach (Tag tag in report) 
     { 

      ushort AntennaNum = tag.AntennaPortNumber; 


      Impinj.OctaneSdk.TagData first = tag.Epc; 

      string epcCheck = first.ToString().ToUpper(); 
      Impinj.OctaneSdk.ImpinjTimestamp tim = tag.LastSeenTime; 

      if (epcCheck.IndexOf("A") != -1) 
      { 

       if (listMed1.Contains(tag) == false) 
       { 
        listMed1.Add(tag); 
        System. Diagnostics.Debug.WriteLine(epcCheck); 
        System.Diagnostics.Debug.WriteLine(tim); 
       } 
      } 

      else if (epcCheck.IndexOf("B") != -1) 
      { 
       if (listMed2.Contains(tag) == false) 
       { 
        listMed2.Add(tag); 
       } 
      } 
      else if (epcCheck.IndexOf("C") != -1) 
      { 
       if (listMed3.Contains(tag) == false) 
       { 
        listMed3.Add(tag); 
       } 
      } 
      else if (epcCheck.IndexOf("D") != -1) 
      { 
       if (listMed1.Contains(tag) == false) 
       { 
        listMed4.Add(tag); 
       } 
      } 
      else if (epcCheck.IndexOf("E") != -1) 
      { 
       if (listMed5.Contains(tag) == false) 
       { 
        listMed5.Add(tag); 
       } 
      } 



      int Med1num = listMed1.Count(); 
      int Med2num = listMed2.Count(); 
      int Med3num = listMed3.Count(); 
      int Med4num = listMed4.Count(); 
      int Med5num = listMed5.Count(); 

      for (int loopr = 0; loopr < Med1num; loopr++) 
      { 
       Impinj.OctaneSdk.ImpinjTimestamp second = listMed1[loopr].LastSeenTime; 
       string milisecondsUTC = second.ToString(); 
       long lastseen = Convert.ToInt64(milisecondsUTC); 
       TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1); 
       long secondsSinceEpoch = (long)t.TotalMilliseconds; 
       if (secondsSinceEpoch - lastseen > 500) 
       { 
        listMed1.RemoveAt(loopr); 
        loopr = -1; 
       } 

      } 
      for (int loopr = 0; loopr < Med2num; loopr++) 
      { 
       Impinj.OctaneSdk.ImpinjTimestamp second = listMed2[loopr].LastSeenTime; 
       string milisecondsUTC = second.ToString(); 
       long lastseen = Convert.ToInt64(milisecondsUTC); 
       TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1); 
       long secondsSinceEpoch = (long)t.TotalMilliseconds; 
       if (secondsSinceEpoch - lastseen > 500) 
       { 
        listMed2.RemoveAt(loopr); 
        loopr = -1; 
       } 

      } 
      for (int loopr = 0; loopr < Med3num; loopr++) 
      { 
       Impinj.OctaneSdk.ImpinjTimestamp second = listMed3[loopr].LastSeenTime; 
       string milisecondsUTC = second.ToString(); 
       long lastseen = Convert.ToInt64(milisecondsUTC); 
       TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1); 
       long secondsSinceEpoch = (long)t.TotalMilliseconds; 
       if (secondsSinceEpoch - lastseen > 500) 
       { 
        listMed3.RemoveAt(loopr); 
        loopr = -1; 
       } 

      } 
      for (int loopr = 0; loopr < Med4num; loopr++) 
      { 
       Impinj.OctaneSdk.ImpinjTimestamp second = listMed4[loopr].LastSeenTime; 
       string milisecondsUTC = second.ToString(); 
       long lastseen = Convert.ToInt64(milisecondsUTC); 
       TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1); 
       long secondsSinceEpoch = (long)t.TotalMilliseconds; 
       if (secondsSinceEpoch - lastseen > 500) 
       { 
        listMed4.RemoveAt(loopr); 
        loopr = -1; 
       } 

      } 
      for (int loopr = 0; loopr < Med5num; loopr++) 
      { 
       Impinj.OctaneSdk.ImpinjTimestamp second = listMed5[loopr].LastSeenTime; 
       string milisecondsUTC = second.ToString(); 
       long lastseen = Convert.ToInt64(milisecondsUTC); 
       TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1); 
       long secondsSinceEpoch = (long)t.TotalMilliseconds; 
       if (secondsSinceEpoch - lastseen > 500) 
       { 
        listMed5.RemoveAt(loopr); 
        loopr = -1; 
       } 

      } 

      Med1num = listMed1.Count(); 
      Med2num = listMed2.Count(); 
      Med3num = listMed3.Count(); 
      Med4num = listMed4.Count(); 
      Med5num = listMed5.Count(); 

      SetText(Med1num, Med2num, Med3num, Med4num, Med5num); 

     } 
    } 
+0

Stimmt es, dass der Parameter 'TagReport' eine Liste aktualisierter Tags ist? Es ist nicht die ganze Liste, aber im Laufe der Zeit feuern mehr 'TagsReported' Ereignisse ab, die Sie für' listMed {X} 'Listen aus den Tags in' TagReport' aufbauen. – Enigmativity

+0

Stimmt das, wenn ich folgendes sage. Sie fügen ALLE Tags zu Ihrer Liste mit dem Namen tag hinzu. Dann verschieben Sie das Tag aus dieser Liste in listMed1, listMed2 usw., je nachdem, wo sie hingehören. Wenn ein Tag nicht in <500 ms angezeigt wurde, wird es aus tag oder listMed1, listMed2 ... entfernt. – Eminem

+0

beide Fragen werden mit ja beantwortet. – Lodestone6

Antwort

0

So:

/// <summary>The group</summary> 
enum eGroup : byte 
{ 
    A, B, C, D, E 
}; 
static IEnumerable<eGroup> allGroups() 
{ 
    return Enum.GetValues(typeof(eGroup)).Cast<eGroup>(); 
} 
/// <summary>Classify tag to the group, returns null if failed.</summary> 
static eGroup? classify(Tag tag) 
{ 
    string str = tag.Epc.ToString().ToUpper(); 
    foreach(eGroup e in allGroups()) 
     if(str.Contains(e.ToString)) 
      return e; 
    return null; 
} 

/// <summary>Add tag to list unless it's already there.</summary> 
static void addToList(List<Tag> list, Tag t) 
{ 
    int ind = list.IndexOf(t); 
    if(ind < 0) 
     list.Add(t); // Not on the list 
    else if(list[ ind ].LastSeenTime.Utc < t.LastSeenTime.Utc) 
     list[ ind ] = t; // Only replace if newer then the existing one 
} 

/// <summary>The collection to hold all that groups.</summary> 
readonly Dictionary<eGroup, List<Tag>> med = allGroups().ToDictionary(e => e, e => new List<Tag>()); 

/// <summary>True if that tag is too old.</summary> 
static bool isTooOld(Tag t) 
{ 
    ImpinjTimestamp ts = t.LastSeenTime; 
    DateTime utc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddTicks((long)ts.Utc * 10L); 
    return (DateTime.UtcNow - utc).TotalMilliseconds > 500; 
} 

void OnTagsReported(ImpinjReader sender, TagReport report) 
{ 
    // Classify and add to the correct group 
    foreach(Tag tag in report) 
    { 
     eGroup? group = classify(tag); 
     if(!group.HasValue) continue; 
     addToList(med[ group.Value ], tag); 
    } 
    // Remove too old tags 
    foreach(var list in med.Values) 
     list.RemoveAll(isTooOld); 

    // Show counts 
    int[] c = allGroups().Select(e => med[ e ].Count).ToArray(); 
    SetText(c[ 0 ], c[ 1 ], c[ 2 ], c[ 3 ], c[ 4 ]); 
} 
+0

Es gibt jedoch ein Problem mit der Übergabe der Gruppen an SetText. Ich versuchte private void SetText (Liste med [eGroup.A], Liste med [eGroup.B], Liste med [eGroup.C], Liste med [eGroup.D], Liste med [eGroup.E]) – Lodestone6

+0

Duplikate Parameter, und A, B, C, D, E existiert nicht in Form1.eGroup – Lodestone6

+0

1 - siehe Update 2 - Sie haben es wahrscheinlich nicht richtig kopiert – Soonts

0

Es scheint mir, dass das alles ist, die Sie benötigen:

void OnTagsReported(ImpinjReader sender, TagReport report) 
{ 
    tags.RemoveAll(tag => report.Select(r => r.Epc).Contains(tag.Epc)); 

    tags.AddRange(report); 

    tags.RemoveAll(tag => 
    { 
     Impinj.OctaneSdk.ImpinjTimestamp second = tag.LastSeenTime; 
     string milisecondsUTC = second.ToString(); 
     long lastseen = Convert.ToInt64(milisecondsUTC); 
     TimeSpan t = DateTime.UtcNow - new DateTime(1970, 1, 1); 
     long secondsSinceEpoch = (long)t.TotalMilliseconds; 
     return secondsSinceEpoch - lastseen > 5000; 
    }); 

    var counts = 
      new[] { "A", "B", "C", "D", "E", } 
       .Select(c => 
        tags 
         .Where(tag => tag.Epc.ToString().IndexOf(c) != -1) 
         .Count()) 
       .ToArray(); 

    SetText(counts[0], counts[1], counts[2], counts[3], counts[4]); 
} 

Die counts Definition könnte das einzige, was Schmerz zu verursachen, aber ich kann es funktionieren lassen, wenn diese grundlegende Art, es zu tun, dir nicht die Ergebnisse gibt, die du brauchst.

Stellen Sie sicher, dass Sie using System.Linq; oben in Ihrem Code haben.


Hier sind die Objektmodelle, die ich für Testzwecke erstellt habe. Es erlaubt den OP-Code und meinen Code zu kompilieren.

public void SetText(params int[] xs) { } 

public class Impinj 
{ 
    public class OctaneSdk 
    { 
     public class TagData { } 
     public class ImpinjTimestamp { } 
    } 
} 

public class ImpinjReader { } 

public class TagReport : List<Tag> { } 

public class Tag 
{ 
    public ushort AntennaPortNumber; 
    public Impinj.OctaneSdk.TagData Epc; 
    public Impinj.OctaneSdk.ImpinjTimestamp LastSeenTime; 
} 
+0

Bericht ist ein TagReport kein Tag, also hat es nicht.auswählen und kann nicht zu einer Liste hinzugefügt werden wie "Tags" – Lodestone6

+0

So habe ich versucht, eine andere Liste aller Tags im Bericht zu erstellen, und dann ersetzt Bericht mit dem Namen dieser Liste in Ihrem Code, und es fügt viele Duplikate – Lodestone6

+0

@ Lodestone6 - 'TagReport' wird in der 'foreach'-Schleife verwendet, also muss es mindestens' IEnumerable ' lauten, was bedeutet, dass Sie ein '.Select' verwenden können. – Enigmativity

0

Sie sollten Sets berücksichtigen, wenn Sie Dubletten verhindern möchten. Abhängig von Ihren Anforderungen kann ein TreeSet für sortierte Daten verwendet werden. In diesem Fall müssen Sie sicherstellen, dass Tag IComparable implementiert. Ansonsten sollte ein HashSet gut passen.
Falls Sie weiterhin Listen verwenden möchten, müssen Sie überschreiben die Equals-Methode auf Tag. Angesichts Ihres Codes können wir die Struktur von Tag nicht sehen, aber Sie verwenden die Methode List.Contains. Sie sollten Equals mit Nichtbeachtung von LastTimeSeen implementieren.
Sie sollten auch nicht IndexOf auf diese Weise verwenden, da es den Code verdeckt, sollten Sie in der Lage sein, es durch String.Contains zu ersetzen. Die Verwendung von Linq, wie es die Enigmativität vorgeschlagen hat, könnte auch Ihren Code stark bereinigen.

Wenn Sie keinen Zugriff auf den Quellcode dieser Bibliothek haben, sollten Sie eine Hilfsmethode oder Erweiterungsmethode für die Sammlung Ihrer Wahl erstellen, in der Sie auf Gleichheit prüfen.

Verwandte Themen