是否有可能“破坏”LINQ to Objects查询?

时间:2011-11-08 02:04:49

标签: c# linq-to-objects

我正在尝试构造一个linq查询,该查询将规则应用于来自两个输入集A和B的域中的布尔函数列表。

但是,我想在找到匹配时“中断”,所以我最终得到A的每个元素最多一个结果。

我希望这对那些经验丰富的功能人员有意义 - 我的意思是我在一条轨道上与那个世界的事情如何完成一致,但我不确定我是否真的在正确的轨道...

这是代码,希望很清楚我在做什么:

List<int> a = new List<int>();
a.Add(1);
a.Add(2);
List<int> b = new List<int>();
b.Add(1);
b.Add(2); 
Func<int, int, string> map = (i, j) => i + "->" + j;
var rules = new List<Func<int,int,Tuple<bool, Func<int, int, string>>>>(); 
rules.Add((i, j) => new Tuple<bool, Func<int,int,string>>(i == j, (ii, jj) => map(ii, jj)));                                  
rules.Add((i, j) => new Tuple<bool, Func<int,int,string>>(i+j == 2, (ii,jj) => map(ii,jj)));                            
var q = from ai in a
        from bi in b
        from rule in rules
        let tuple = rule(ai, bi)
        where tuple.Item1 == true
        select tuple.Item2(ai, bi);  

结果是:

1->1

1->1

2->2

期望的结果:

1->1

2->2

喜欢发生的事情是当第一个规则与1-> 1匹配时,我可以排除第二个1-&gt; 1。似乎这将允许我按顺序应用主要规则和回退规则,但不会产生额外的映射。

2 个答案:

答案 0 :(得分:3)

听起来你正在寻找enumerable.TakeWhile(predicate)

来自MSDN的示例:

        string[] fruits = { "apple", "banana", "mango", "orange", 
                              "passionfruit", "grape" };

        IEnumerable<string> query =
            fruits.TakeWhile(fruit => String.Compare("orange", fruit, true) != 0);

        foreach (string fruit in query)
        {
            Console.WriteLine(fruit);
        }

        /*
         This code produces the following output:

         apple
         banana
         mango
        */

答案 1 :(得分:1)

这是明显发挥作用的地方。由于每个规则都由其规则表示唯一标识,因此您只需在输出上执行不同的操作,即:

        var q = from ai in a
                from bi in b
                from rule in rules
                let tuple = rule(ai, bi)
                where tuple.Item1 == true
                select tuple.Item2(ai, bi);

        q = q.Distinct().ToArray();

将导致:

1->1 

2->2 

而不是

1->1   

1->1   

2->2