linq - Left Join LINQ 并使用按位比较

标签 linq linq-to-objects

左连接 LINQ 并使用按位比较。

我有一个问题可以描述为(感谢 David B 澄清了这一点): 目标是从左表中为每个 OID 返回 1 行,其中左表中记录的计数等于右表中匹配行的计数。当一行的 OID、RID 和 FLAG 设置在 FLAGS 中时,一条记录匹配。

我们正在比较的对象具有以下结构:

public class Roads : List<Road>{}
public class Road
{
    public int RID;
    public int OID;
    public int Check = 1;
    public long Flag;
}
public class Cars : List<Car> { }
public class Car
{
    public int RID;
    public int OID;
    public long Flags;
}

对象中填充了以下数据。

        Roads rs = new Roads();
        Cars cs = new Cars();

        Car c = new Car();
        c.OID = 1;
        c.RID = 1;
        c.Flags = 31; // 11111
        cs.Add(c);
        c = new Car();
        c.OID = 1;
        c.RID = 2;
        c.Flags = 31; //11111
        cs.Add(c);
        c = new Car();
        c.OID = 1;
        c.RID = 3;
        c.Flags = 4; //00100
        cs.Add(c);

        Road r = new Road();
        r.OID = 1;
        r.RID = 1;
        r.Flag = 8; //00010
        rs.Add(r);
        r = new Road();
        r.OID = 1;
        r.RID = 2;
        r.Flag = 2; //01000
        rs.Add(r);
        r = new Road();
        r.OID = 1;
        r.RID = 3;
        r.Flag = 4;  //01000
        rs.Add(r);
      //  r = new Road();
      //  r.OID = 1;
      //  r.RID = 3;
      //  r.Flag = 16;  //00001
      //  rs.Add(r);

要查看是否设置了标志,您可以进行按位比较,即 cs[0].Flags && rs[0].Flag > 0 为 TRUE,cs[0].Flags & rs[0].Flag = 0是假的

我有一个通用查询,它将为我获取 cs 中 OID 计数 = rs 中匹配 OID 计数的行。我现在需要一个修改后的查询,其中应用了其余规则。我们检查 Flag 是否在特定行匹配的 Flag 中。

    var carLookup = cs.ToLookup(cb => c.OID);
    var roadLookup = rs.ToLookup(rb => r.OID);

    var results1 = from x in carLookup
                   let carCount = x.Count()
                   let roadCount = roadLookup[x.Key].Count()
                   where carCount == roadCount
                   select new {  OID = x.Key, CarCount = carCount, RoadCount = roadCount };

我如何扩展它以应用额外的过滤条件?我正在苦苦挣扎的是在我需要它们的地方提供可用的列来建立适当的过滤条件。比如我需要比较Flags && Flag。但是我怎样才能得到 Flag 和 Flags 来做额外的过滤呢?

展开。我主要使用 TSQL,所以我试图模仿可以轻松应用于 TSQL 的逻辑流。如果我用 TSQL 这样做,它看起来像这样(注意 0 的特殊情况):

SELECT cs.OID, Count(cs.OID) AS CarCount, Sum(RS.Check) AS RoadCount  
   FROM Cars AS cs  
LEFT JOIN Roads AS RS  
  ON CS.oid = RS.OID  
 AND cs.RID = RS.RID  
 AND (CS.FLAGS & RS.FLAG > 0
      OR (CS.FLAGS=0 AND RS.FLAG=0))
GROUP BY cs.OID  
HAVING Count(cs.OID) = Sum(RS.Check)   

使用该语句和上面的数据,结果将是 1、3、3。

如果我要注释最后添加到 Roads,并取消注释下一行,将 Flag 更改为 16,那么结果将是: 无效的 如果您需要更多信息,请发表评论。

最佳答案

我认为这应该等同于您的 SQL 语句,但是它没有产生您提到的结果,因为您的 SQL 使用 RS.Check 但您没有分配任何 Check 示例代码中的值(您使用了 r.OID)。我继续将 r.Check = 1; 添加到每个 Road 对象,并且能够得到你提到的结果。

var query = from car in cs
            from road in rs
            where car.OID == road.OID
                && car.RID == road.RID
                && ((car.Flags & road.Flag) > 0 || (car.Flags == 0 && road.Flag == 0))
            group new { car, road } by car.OID into grouping
            let CarCount = grouping.Count()
            let RoadCount = grouping.Sum(o => o.road.Check)
            where CarCount == RoadCount
            select new { OID = grouping.Key, CarCount, RoadCount };

关于linq - Left Join LINQ 并使用按位比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4179550/

相关文章:

c# - 使用Linq从等长数组中获取不同元素的索引

c# - 使用 LINQ 按值过滤字典时遇到麻烦

sql - Linq 自连接组合键

c# - 如何在C#中使用Ienumerable获取替代元素

c# - 如何从 Dictionary<int, string> 中提取 List<int>?

c# - 将列表列表转换到 IGrouping?

c# - 遍历树时查找节点

LINQ: 自连接查询,如何实现?

c# - IEnumerable<T>/IQueryable<T> 上的动态 LINQ OrderBy

c# - Enumerable.OfType<>() 无法按预期方式使用路由集合