Search code examples
c#listsortingrfid

Removing Duplicates From a list while keeping the most recent C#


So I have several lists of type Tag. Tag has several properties: .Epc , .AntennaPortNumber, and .LastTimeSeen. I want to take all of the Tags from the main list, and sort them into 5 smaller lists, but only keep one copy of each .Epc and it must be the most recent .LastTimeSeen. I am not really sure where to even begin. I was thinking I must need to do something with .GroupBy nested a couple times? right now the code is split into two main parts: where I add new tags to the lists they belong in, and where I remove a tag that has not been seen for 500ms. I attempted to prevent duplicate tags from being added to the 5 sublists with .Contains, but because they have different LastTimeSeen properties this is not having the desired effect.

Thanks for any guidance anyone might be able to provide!

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

        } 
    }

Solution

  • Like this:

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