【问题标题】:How to properly compare lists [duplicate]如何正确比较列表[重复]
【发布时间】:2012-04-03 21:07:49
【问题描述】:

可能重复:
Compare two Lists for differences

这是我的功能

    public List<String[]> comparableListsAreTheSame(List<String> baseList, List<String> resultList, int type)
    {
        if (type == 1) { }

        List<String> baseListCopy = baseList;
        List<String> resultListCopy = resultList;

        bool sameLength = (baseListCopy.Count == resultList.Count); // are 2 lists have the same length?

        List<String> Base = baseListCopy.Except(resultListCopy, StringComparer.InvariantCultureIgnoreCase).ToList(); //Keep unique values 
        List<String> Result = resultListCopy.Except(baseListCopy, StringComparer.InvariantCultureIgnoreCase).ToList(); //Keep unique values 

        List<String[]> blocksComparisonSet1 = new List<String[]>(); //we add blocks based on list1; so we could output them to excel
        List<String[]> blocksComparisonSet2 = new List<String[]>(); //we add blocks based on list2; so we could output them to excel
        List<String[]> blocksComparisonFinal = new List<String[]>(); //we combine list1 and list

        //-----------------------------------------------------------------

        if (Result.Count > 0 || Base.Count > 0)
        {
            foreach (String resultLine in Result) //loop over all lines in list 1
            {
                bool found = false; //if element in base i
                String[] resultLineArray = resultLine.Split('*'); //get array from the string
                foreach (String baseLine in Base)
                {
                    String[] baseLineArray = baseLine.Split('*');
                    if (resultLineArray[0].Equals(baseLineArray[0]) && resultLineArray[1].Equals(baseLineArray[1]) && resultLineArray[2].Equals(baseLineArray[2]) && resultLineArray[3].Equals(baseLineArray[3]))
                    {
                        String[] NA = new String[2]; //keep results
                        NA[0] = baseLine; //[0] for base
                        NA[1] = resultLine; //[1] for result
                        blocksComparisonSet1.Add(NA);
                        found = true;
                    }
                }

                if (!found)
                {
                    String[] NA = new String[2]; //keep results
                    NA[0] = "N/A"; //[0] for base
                    NA[1] = resultLine; //[1] for result
                    blocksComparisonSet1.Add(NA);
                }
            }


            //-----------------------------------------------------------------
            foreach (String baseLine in Base) //loop over all lines in list 2
            {
                bool found = false; //if element in base i
                String[] baseLineArray = baseLine.Split('*'); //get array from the string
                foreach (String resultLine in Result)
                {
                    String[] resultLineArray = resultLine.Split('*');
                    if (resultLineArray[0].Equals(baseLineArray[0]) && resultLineArray[1].Equals(baseLineArray[1]) && resultLineArray[2].Equals(baseLineArray[2]) && resultLineArray[3].Equals(baseLineArray[3]))
                    {
                        String[] NA = new String[2]; //keep results
                        NA[0] = baseLine; //[0] for base
                        NA[1] = resultLine; //[1] for result
                        blocksComparisonSet2.Add(NA);
                        found = true;
                    }
                }

                if (!found)
                {
                    String[] NA = new String[2]; //keep results
                    NA[0] = baseLine; //[0] for base
                    NA[1] = "N/A"; //[1] for result
                    blocksComparisonSet2.Add(NA);
                }
            }
        }

        //-----------------------------------------------------------------
        if (blocksComparisonSet1.Any() || blocksComparisonSet2.Any()) //check if we have any values in out differences lists. if we do, merge them
        {
            blocksComparisonFinal.AddRange(blocksComparisonSet1); //add records from one list to final list
            blocksComparisonFinal.AddRange(blocksComparisonSet2); //add records from second list to final list
            HashSet<String[]> s = new HashSet<String[]>(blocksComparisonFinal);
            blocksComparisonFinal = s.ToList();
        }
        blocksComparisonFinal = blocksComparisonSet1.Union(blocksComparisonSet2, new ArrayEqualityComparer<string>()).ToList();
        return blocksComparisonFinal;
    }

我是 C# 和一般编程的新手,我做了多个循环并以非常粗俗的方式匹配所有内容。我可以更专业地处理它,并且做得更干净、更正确吗?

【问题讨论】:

  • 定义列表“平等”的含义。
  • 可能更适合 codereview.stackexchange.com
  • type 参数是干什么用的?一般来说,您可以创建一个实现IEqualityComparer&lt;List&lt;string[]&gt;&gt; 的类和/或一个实现IEqualityComparer&lt;string[]&gt; 的类,以大大简化您的代码。
  • 看起来您要做的不仅仅是确定两个列表是否相等...您能否详细解释一下您要完成的工作?

标签: c# algorithm list optimization comparison


【解决方案1】:

如果您正在检查 listA 和 listB 是否具有相同的元素,您可以使用此扩展方法:

public static IEnumerable<TSource> Intersect<TSource>
(
    this IEnumerable<TSource> first,
    IEnumerable<TSource> second,
    Func<TSource, TSource, bool> comparer
)
{
    return first.Intersect(second, new LambdaComparer<TSource>(comparer));
}

其中使用LambdaComparer 类。

然后你可以用这种方式比较它们:

var compared = listA.Intersect(listB, (a, b) => a == b);
if(compared.Count() == listA.Count())
   // they are the same
else
   // they are not

【讨论】:

    【解决方案2】:

    我只有几个 cmets。

    可以用 List.Contains 方法替换最里面的 foreach 循环。当您可以直接比较字符串时,您通过将其拆分为一个数组然后循环遍历该数组来增加一堆开销。 http://msdn.microsoft.com/en-us/library/bhkz42b3.aspx

    另外,您的第二个循环遍历列表 2 中的所有行,只需要跟踪未命中,而不是命中。第一个循环找到 (1 & 2) 和 (1 & not 2) 中的项目,因此第二个循环只需要在有意义的情况下找到 (不是 1 & 2) 的项目。这也将使您不必在最后将命中/未命中列表合并在一起。

    如果您倾向于先对列表进行排序,则可以更有效、更整洁地进行此操作。

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-04
      • 2019-09-14
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      相关资源
      最近更新 更多