在保留最新C#的同时从列表中删除重复项

时间:2016-03-23 05:40:31

标签: c# list sorting rfid

所以我有几个Tag类型的列表。 Tag有几个属性:.Epc,.AntennaPortNumber和.LastTimeSeen。我想从主列表中取出所有标签,并将它们分成5个较小的列表,但只保留每个.Epc的一个副本,它必须是最新的.LastTimeSeen。我不确定从哪里开始。我以为我必须要用.GroupBy嵌套几次?现在,代码分为两个主要部分:我将新标记添加到它们所属的列表中,以及删除500ms内未见过的标记。我试图阻止使用.Contains将重复标记添加到5个子列表中,但由于它们具有不同的LastTimeSeen属性,因此没有达到预期的效果。

感谢任何人可能提供的任何指导!

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

        } 
    }

3 个答案:

答案 0 :(得分: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 ] );
}

答案 1 :(得分:0)

在我看来,这就是你可能需要的全部内容:

--junitxml

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

这是我为测试目的而创建的对象模型。它允许OP的代码和我的代码进行编译。

using System.Linq;

答案 2 :(得分:0)

如果要防止重复,则应考虑设置。根据您的需要,TreeSet可用于排序数据,在这种情况下,您必须确保Tag实现IComparable。否则HashSet应该很合适 如果您想继续使用列表,必须覆盖标记上的等于方法。鉴于您的代码,我们无法看到Tag的结构,但您使用List.Contains方法。你应该在不考虑LastTimeSeen的情况下实现Equals 您也不应该以这种方式使用IndexOf,因为它会掩盖代码,您应该能够用String.Contains替换它。使用Linq作为Enigmativity建议也可以大大清理你的代码。

如果您无权访问该库的源代码,则应在所选集合上创建辅助方法或扩展方法,以检查其是否相等。