【问题标题】:c# Intersection and Union not working correctlyc# Intersection 和 Union 无法正常工作
【发布时间】:2013-04-07 21:28:19
【问题描述】:

我在 VS 2010 中使用 C# 4.0 并尝试生成 n 组对象的交集或并集。

以下工作正常:

IEnumerable<String> t1 = new List<string>() { "one", "two", "three" };
IEnumerable<String> t2 = new List<string>() { "three", "four", "five" };

List<String> tInt = t1.Intersect(t2).ToList<String>();
List<String> tUnion = t1.Union(t2).ToList<String>();
//  this also works
t1 = t1.Union(t2);
//  as does this (but not at the same time!)
t1 = t1.Intersect(t2);

但是,以下不是。这些是代码 sn-ps。

我的班级是:

 public class ICD10
{
    public string ICD10Code { get; set; }
    public string ICD10CodeSearchTitle { get; set; }
}

如下:

IEnumerable<ICD10Codes> codes = Enumerable.Empty<ICD10Codes>();
IEnumerable<ICD10Codes> codesTemp;
List<List<String>> terms;
//  I create terms here ----
// and then ...
foreach (List<string> item in terms)
{
    //  the following line produces the correct results
    codesTemp = dataContextCommonCodes.ICD10Codes.Where(e => item.Any(k => e.ICD10CodeSearchTitle.Contains(k)));

    if (codes.Count() == 0)
    {
        codes = codesTemp;
    }
    else if (intersectionRequired)
    {
        codes = codes.Intersect(codesTemp, new ICD10Comparer());
    }
    else
    {
        codes = codes.Union(codesTemp, new ICD10Comparer());
    }                
}
return codes;

上面只返回最后一个搜索项目的结果。

我还添加了自己的比较器以防万一,但这并没有什么区别:

public class ICD10Comparer : IEqualityComparer<ICD10Codes>
{
    public bool Equals(ICD10Codes Code1, ICD10Codes Code2)
    {
        if (Code1.ICD10Code == Code2.ICD10Code) { return true; }
        return false;
    }
    public int GetHashCode(ICD10Codes Code1)
    {
        return Code1.ICD10Code.GetHashCode();
    }
}

我确定我忽略了一些明显的东西 - 我只是看不到它是什么!

【问题讨论】:

  • 尝试在循环内移动codesTemp的声明,即IEnumerable&lt;ICD10Codes&gt; codesTemp = dataContextCommonCodes.ICD1...
  • 谢谢 Joachim,好主意。可悲的是,这没什么区别。
  • 错过了一件事,您还需要做List&lt;string&gt; tmpItem = item; 并在dataContextCommonCodes Linq 表达式中使用tmpItem 而不是item

标签: c# linq search intersection


【解决方案1】:

此代码:return codes; 返回一个延迟枚举。没有执行任何查询来填充集合。每次循环都会执行一些查询以进行计数。

这个延迟执行是一个问题,因为闭包问题......在返回时,item 被绑定到最后一个循环执行。

通过在每个循环执行中强制执行查询来解决此问题:

if (codes.Count() == 0)
{
    codes = codesTemp.ToList();
}
else if (intersectionRequired)
{
    codes = codes.Intersect(codesTemp, new ICD10Comparer()).ToList();
}
else
{
    codes = codes.Union(codesTemp, new ICD10Comparer()).ToList();
}   

【讨论】:

  • +1 是的,这就是解释,另一种方法是将item 保存在循环内声明的临时变量中,这样它就永远不会更新。
  • +1 非常感谢大卫,非常感谢你的工作、现场和所有其他短语
【解决方案2】:

如果您使用自己的比较器,您应该查看GetHashCode 函数的正确实现。 linq 运算符也使用这种比较。你可以看看这里: http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.80).aspx

您可以尝试将哈希函数更改为“返回 0”,看看是否是问题所在。 ICD10Code.GetHashCode 如果是类对象,可能会返回不同的值

【讨论】:

    【解决方案3】:

    您的问题绝对不是连接到IntersectUnion LINQ 扩展方法。我刚刚测试了以下内容:

    var t1 = new List<ICD10>()
        {
            new ICD10() { ICD10Code = "123" },
            new ICD10() { ICD10Code = "234" },
            new ICD10() { ICD10Code = "345" }
        };
    var t2 = new List<ICD10>()
        {
            new ICD10() { ICD10Code = "234" },
            new ICD10() { ICD10Code = "456" }
        };
    
    // returns list with just one element - the one with ICF10Code == "234"
    var results = t1.Intersect(t2, new ICD10Comparer()).ToList();
    
    // return list with 4 elements
    var results2 = t1.Union(t2, new ICD10Comparer()).ToList();
    

    使用您的 ICD10ICD10Comparer 类声明。一切正常!您必须在自定义代码中搜索错误,因为 LINQ 工作正常。

    【讨论】:

    • 他使用item 的表达式在循环中不能很好地工作,因为item 在计算表达式之前发生了变化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-11
    • 2018-02-15
    • 2016-03-15
    • 2011-08-31
    • 2020-08-01
    • 2013-08-26
    • 2010-11-29
    相关资源
    最近更新 更多