如何基于C#中的匹配键比较IEnumerable <dictionary <string,object =“” >>

时间:2019-03-07 23:59:26

标签: c# linq

我想比较两个不同列表(源列表和目标列表)中的数据。他们是两个不同的IEnumerable<Dictionary<string, object>>

我正在运行两个测试,每个测试的结果应从目标输出缺少的记录,并将缺少的记录分配给新的IEnumerable<Dictionary<string, object>>

两个Dictionary<string, object>中的键始终相同。但是,列表的长度和字典中的值可能不是。

清单1:

enter image description here enter image description here enter image description here

清单2:

enter image description here enter image description here enter image description here

这是我尝试的方法,但是它仅比较列表的第一个键和值。 我想知道每个列表中的键是否有不同的值。

我的控制器:

    [HttpPost]
    public ActionResult TestResult(ValidationTestVM model)
    {

           model.NotFoundInSource = ServiceLayer.RecordCountResults(sourceQueryResults, targetQueryResults).ToList();

           model.NotFoundInTarget = ServiceLayer.RecordCountResults(targetQueryResults, sourceQueryResults).ToList();
     }

服务类别:

     public static IEnumerable<Dictionary<string, object>> RecordCountResults(IEnumerable<Dictionary<string, object>> source, IEnumerable<Dictionary<string, object>> target)
     {
            var results = new List<Dictionary<string, object>>();

            if((source != null && target != null) || (source.Count() > 0 && target.Count() > 0))
                results = source.Where(m =>!target.Select(s => s.First().Value).Contains(m.First().Value)).ToList();            

            return results;
     }

这似乎无法正常工作。有人可以告诉我我在做什么错吗?

创建样本数据并显示我期望如何看到退货清单的虚拟方法:

        public static void DummyData(IEnumerable<Dictionary<string, object>> source, IEnumerable<Dictionary<string, object>> target)
        {
            // Dummy Data
            List<Dictionary<string, object>> lSource = source.ToList();
            List<Dictionary<string, object>> lTarget = target.ToList();

            for (int i = 0; i < 3; i++)
            {
                var sourceDic1 = new Dictionary<string, object>();
                sourceDic1.Add("Field1", "2017");
                sourceDic1.Add("Field2", "2018");
                sourceDic1.Add("Field3", "2019");
                sourceDic1.Add("Field4", "2018_E_" + i);

                lSource.Add(sourceDic1);                
            }


            for (int i = 2; i < 4; i++)
            {
                var targetDic2 = new Dictionary<string, object>();
                targetDic2.Add("Field1", "2017");
                targetDic2.Add("Field2", "2018");
                targetDic2.Add("Field3", "2019");
                targetDic2.Add("Field4", "2018_E_" + i);

                lTarget.Add(targetDic2);
            }


            // Results 
            var DoesNotExistInTarget = new List<Dictionary<string, object>>();
            var DoesNotExistInSource = new List<Dictionary<string, object>>();

            for (int i = 0; i < 2; i++)
            {
                var MissingDic1 = new Dictionary<string, object>();
                MissingDic1.Add("Field1", "2017");
                MissingDic1.Add("Field2", "2018");
                MissingDic1.Add("Field3", "2019");
                MissingDic1.Add("Field4", "2018_E_" + i);

                DoesNotExistInTarget.Add(MissingDic1);
            }

            for (int i = 3; i < 4; i++)
            {
                var MissingDic2 = new Dictionary<string, object>();
                MissingDic2.Add("Field1", "2017");
                MissingDic2.Add("Field2", "2018");
                MissingDic2.Add("Field3", "2019");
                MissingDic2.Add("Field4", "2018_E_" + i);

                DoesNotExistInSource.Add(MissingDic2);
            }    
        }        

1 个答案:

答案 0 :(得分:1)

好的,我已经根据您的问题更新了我的答案。

您将需要一种方法来检查字典是否相等。

下面的一个期望根据需要在两个字典中具有相同的键,但是如果碰巧具有不同的键,只需在现有的相等性检查之前添加一个检查即可。

我已将其实现为扩展方法,因此更易于使用:

public static class DictionaryExtensions
{
    /// <summary>
    /// Expected to have 2 dictionaries with same keys
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="dict1"></param>
    /// <param name="dict2"></param>
    /// <returns></returns>
    public static bool IsEqual<T>(
        this Dictionary<string, T> dict1,
        Dictionary<string, T> dict2)
    {
        foreach (var keyValuePair in dict1)
        {
            if (!keyValuePair.Value.Equals(dict2[keyValuePair.Key]))
                return false;
        }

        return true;
    }
}

然后在RecordCountResult方法中使用以下代码:

    public static IEnumerable<Dictionary<string, object>> RecordCountResults(
        IEnumerable<Dictionary<string, object>> source,
        IEnumerable<Dictionary<string, object>> target)
    {
        foreach (var sourceDictionary in source)
        {
            var existsInTarget = false;

            foreach (var targetDictionary in target)
            {
                if (sourceDictionary.IsEqual(targetDictionary))
                {
                    existsInTarget = true;
                    break;
                }    
            }

            if (!existsInTarget)
                yield return sourceDictionary;
        }
    }

这个想法是,您必须首先循环遍历源字典,并针对每个sourceDictionary检查目标列表中是否有匹配项。如果您的sourceDictionary在目标中不匹配,则将报告它。

我不想在RecordCountResults方法中使用Linq,因为使用foreach更具可读性和理解性。

还要注意,我使用的是yield return而不是临时候选人名单。如果您喜欢临时列表,请随时进行更改。