【问题标题】:Pre-filtering joined elements in LINQ to Objects在 LINQ to Objects 中预过滤连接的元素
【发布时间】:2015-05-04 21:22:00
【问题描述】:

我有两个集合,'left' 和 'right',具有不同的元素类型。元素类型都有一个字符串属性“paramNumber”,它不是唯一的,并且通过它的关系是多对多的。现在,有两个 DateTime 字段,“left.date”和“right.startDate”。对于每个选定的“left.date”,我需要获取“right”中的最后一个元素,其中“right.startDate”小于或等于(除了连接条件“left.paramNumber”==“right.paramNumber”)。

我想知道是否有没有完全交叉连接的直接方法?我尝试了一个子查询,但遇到了“lefty”变量范围的问题(参见代码)。

我在网上看到教程先进行完全交叉连接,然后删除 'where' 子句中不需要的行,但这对我们来说是没有选择的。

class left
{
    public string paramNumber;
    public DateTime date;
    public string leftyName;
}

class right
{
    public string paramNumber;
    public DateTime startDate;
    public string anotherString;
    public DateTime timeOfDay;
}

class Program
{
    static void Main(string[] args)
    {

        List<left> lefts = new List<left>();
        List <right> rights = new List <right>();

        //lefty not visible in the where clause...
        //trying it with a second 'from right...' did not work because of
        //casting problems.
        var query =
            from left lefty in lefts
            join right righty in
               ((from right rightTmp in rights
                 where ((rightTmp.paramNumber == lefty.paramNumber) &&
                        (rightTmp.startDate <= lefty.date) &&
                        (rightTmp.anotherString == "N") )
                 select rightTmp
                ).ToList().Last())
            on lefty.paramNumber equals righty.paramNumber
            select new
            {
                myDate = lefty.date,
                myLeftyName = lefty.leftyName,
                myParamNumber = lefty.paramNumber,
                myTimeOfDay = righty.timeOfDay
            };
    }
}

[编辑]:解决方案(基于 cechode 的回答):

以下是我目前使用的解决方案,基于 cechode 的回答。 'let' 子句是主要缺失的部分,因为它也允许引用 l/lefty,而不仅仅是 r/rightTmp。

最后,我对其中的一个所需元素进行了全面过滤 'rights' 直接在第一个 'let' 子句中(通过升序排序并使用 最后的();当然 cechode 的 descending/First() 也有效)并避免了第二个 使用 'toprightcheck' 变量(我认为 cechode 有充分的理由进行空检查,但我会尝试使用较短的版本):

var X = (from l in lefts
         let topright =
            (from r in rights
             where r.paramNumber == l.paramNumber && 
                   r.startDate <= l.date
             orderby r.startDate ascending
             select r).Last()        
         select new {
            lName = l.paramNumber,
            rname = topright.paramNumber,
            ldate = l.date,
            rdate = topright.startDate });

【问题讨论】:

    标签: c# linq filter


    【解决方案1】:

    这对你有用吗?

    var X = (from l in lefts
            let topright = (from r in rights where r.paramNumber == l.paramNumber && r.startDate < l.date orderby r.startDate descending select r)
            where topright!=null
            let toprightcheck = topright.First()
         select new { lName = l.paramNumber, rname = toprightcheck.paramNumber, ldate = l.date, rdate = toprightcheck.startDate });
    

    【讨论】:

    • 嗨 cechode,非常感谢您的帮助,成功了!请参阅我对问题的编辑,了解我最终得出的变体。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 2011-10-22
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多