Linq 索引选择(取两个)

本文关键字:两个 索引 选择 Linq | 更新日期: 2023-09-27 18:35:54

好的,我知道Select((x, i) => ...)没有文字形式,但我有一个相当复杂的查询,现在有一个新的要求,使一半的投影输出字段依赖于输出"行号"。有没有办法,即使是丑陋的方法,也可以引入索引并以文字形式保留一个查询?

另请注意,并非所有源行都参与结果,因此我不能只是将源投影到可枚举的索引元组中,索引必须在最终投影之前以及所有连接和位置之后应用。

编辑:

原始查询很大,所以把它放在这里毫无意义,让我们用伪简化

from a in source
where somecondition(a)
join b in source2 on a.key equals b.key
where someothercondition(a, b)
select new
{
    f1 = a.f1,
    oldf2 = func(a.field, b.field),
    newf2 = func(a.field, b.field, index)
    // ... (20 somthing more projected fields)
}

我需要 newf2 的索引,我需要它而不将查询拆分为两个查询

Linq 索引选择(取两个)

如果你想要这个"在一个查询中",大多数是"文字形式",你必须执行以下操作:

from t in
    (
        (
            from a in source
            where somecondition(a)
            join b in source2
            on a.key equals b.key
            where someothercondition(a, b)
            select new { a = a, b = b }
        ).Select((x, i) => new { index = i, a = x.a, b = x.b } )
    )
select new {
    f1 = t.a.f1,
    oldf2 = func(t.a.field, t.b.field),
    newf2 = func(t.a.field, t.b.field, t.index)
    // ... (20 somthing more projected fields) } 

但这太可怕了

我宁愿以.形式将其全部呈现:

a
    .Where(a => somecondition(a))
    .Join(b, a => a.key, b => b.key, (a,b) => new { a = a, b = b })
    .Where(pair => somecondition(pair.a, pair.b))
    .Select((t, i) => new
        {
            f1 = t.a.f1,
            oldf2 = func(t.a.field, t.b.field),
            newf2 = func(t.a.field, t.b.field, i)
            // ...
        });

联接语法更丑陋,但至少你没有混淆语法。

你甚至可能更喜欢做

var pairs = 
    from a in source
    where somecondition(a)
    join b in source2
    on a.key equals b.key
    where someothercondition(a, b)
    select new { a = a, b = b };
var indexedPairs = pairs.Select((x, i) => new { index = i, a = x.a, b = x.b } );
var projectedIndexedPairs =
    from t in indexedPairs
    select new {
        f1 = t.a.f1,
        oldf2 = func(t.a.field, t.b.field),
        newf2 = func(t.a.field, t.b.field, t.index)
        // ... (20 somthing more projected fields)
        };

但这不是"在一个查询中"...

(这是很多 LINQ,其中可能存在一些语法错误,但您可以大致了解。

令人眼花缭乱的灵感闪光

你提到let魔法让我想起了这一点。它似乎在我写的一个快速示例中有效。

// Copious commenting to explain what you're doing.
int x = 0;
// Copious commenting to explain what you're doing.
var query =
    from a in source
    where somecondition(a)
    join b in source2
    on a.key equals b.key
    where someothercondition(a, b)
    let i = x++
    select new {
        f1 = a.f1,
        oldf2 = func(a.field, b.field),
        newf2 = func(a.field, b.field, i),
        // ... (20 somthing more projected fields)
        };

更新:这是相当脆弱的。例如,如果迭代query两次,索引将不断递增。(即它不会重置为零。