2016-03-23 6 views
1

Итак, у меня есть несколько списков типа Tag. Тег имеет несколько свойств: .Epc, .AntennaPortNumber и .LastTimeSeen. Я хочу взять все теги из основного списка и отсортировать их по 5 меньшим спискам, но сохранить только одну копию каждого .Epc, и это должен быть самый последний .LastTimeSeen. Я не совсем уверен, с чего начать. Я думал, что мне нужно что-то сделать с .GroupBy вложено пару раз? прямо сейчас код разбит на две основные части: где я добавляю новые теги в списки, в которые они входят, и где я удаляю тег, который не был замечен за 500 мс. Я попытался запретить добавление повторяющихся тегов в 5 подписок с помощью .Contains, но поскольку у них разные свойства LastTimeSeen, это не имеет желаемого эффекта.Удаление дубликатов Из списка, сохраняя последний C#

Спасибо за любые рекомендации, которые кто-либо может предоставить!

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

Я правильно говорю, что параметр «TagReport» - это список обновленных тегов? Это не весь список, но со временем больше событий с событиями «TagsReported», которые вы создаете для списков listMed {X} 'из тегов в« TagReport ». – Enigmativity

+0

Правильно ли я говорю следующее. Вы добавляете ВСЕ теги к списку с именем tag. Затем из этого списка вы перемещаете тег в listMed1, listMed2 и т. Д., В зависимости от того, где они принадлежат. Если тег не был замечен в <500 мс, он удаляется из тега или listMed1, listMed2 ...? – Eminem

+0

Ответы на два вопроса: да. – Lodestone6

ответ

0

Как это:

/// <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

есть какая-то проблема с передачей групп в SetText. Список профайлов med [eGroup.A], Список med [eGroup.B], Список med [eGroup.C], Список med [eGroup.D], Список med [eGroup.E]) – Lodestone6

+0

Параметр дублирования и A, B, C, D, E не существует в Form1.eGroup – Lodestone6

+0

1 - см. Обновление 2 - вы, вероятно, не смогли правильно скопировать-вставить – Soonts

0

Мне кажется, что это все, что вам может понадобиться:

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

counts определение может быть единственное, что горе, но я может заставить его работать, если этот основной способ сделать это не дает вам результатов, которые вам нужны.

Убедитесь, что у вас есть using System.Linq; в верхней части вашего кода.


Вот модели объектов, которые я создал для целей тестирования. Это позволяет компилировать код OP и мой код.

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

отчет является тегом TagReport, а не тегом, поэтому он не имеет.выберите и не может быть добавлен в список как «теги» – Lodestone6

+0

Итак, я попытался создать еще один список всех тегов в отчете, а затем заменить отчет на имя этого списка в вашем коде и добавит много дубликатов – Lodestone6

+0

@ Lodestone6 - 'TagReport' используется в цикле' foreach', поэтому он должен по крайней мере быть 'IEnumerable ', что означает, что вы можете использовать '.Select' против него. – Enigmativity

0

Следует учитывать, если вы хотите предотвратить дубликаты. В зависимости от ваших потребностей TreeSet может использоваться для сортированных данных, и в этом случае вы должны убедиться, что Tag реализует IComparable. В противном случае HashSet должен хорошо сочетаться.
В случае, если вы хотите продолжить использование списков, вы: должны переопределить метод Equals на теге. Учитывая ваш код, мы не можем видеть структуру Tag, но вы используете метод List.Contains. Вы должны реализовать Equals с пренебрежением к LastTimeSeen.
Вы также не должны использовать IndexOf таким образом, чтобы он скрывал код, вы должны заменить его на String.Contains. Использование Linq как Enigmativity предложило также значительно очистить ваш код.

Если у вас нет доступа к исходному коду этой библиотеки, вы должны сделать вспомогательный метод или метод расширения в коллекции выбора, в которой вы проверяете равенство.

Смежные вопросы