【问题标题】:How to leverage dynamic programming inside of a Linq Where clause?如何在 Linq Where 子句中利用动态编程?
【发布时间】:2020-04-08 02:24:53
【问题描述】:

我正在尝试找到一种方法来传递或使用 .Where() 子句中的集合来加快执行速度,但没有任何运气。这是我想做的:

var matches = superLongEnumerable.Where((x, HashSet<string> dynamicSet) => 
    {
        var parent = SemiExpensiveCallToGetParent(x);
        if(dynamicSet.Contains(parent))
        {
            // DP optimization to save further computation
            return true;
        }
        var matched = ExpensiveCallToCheckMatch(parent);
        if(matched) {
            dynamicSet.Add(parent);
        }
        return matched;
    });

据我所知,.Where() 仅支持当前元素,并且可选地支持当前元素的索引。我可以使用.Where() 的替代品吗?

【问题讨论】:

    标签: c# .net linq dynamic-programming


    【解决方案1】:

    由于这显然是 LINQ to entity,因此您始终可以为简单的场景使用简单的 for 或 foreach,或者构建一个枚举器函数。

    但是性能的主要问题是:您只保存昂贵测试的结果,以防成功,不成功的昂贵调用您一次又一次地重复。 所以字典可能更有用。

    Where would be的替代方案

     public IEnumerable<string> MyFilter(IEnumerable<string> source)
     {
          var temp = new Dictionary<string, bool>();
          foreach(var item in source)
          {
               var parent = SemiExpensiveCallToGetParent(item);
               if (temp.TryGetValue(parent, out bool result))
               {
                   if (result)
                        yield return item;
               }
    
               var matched = ExpensiveCallToCheckMatch(parent);
               temp.Add(parent, matched);
               if (matched)
                   yield return item;
          }
      }
    

    如果你喜欢 WHERE,你可以使用类方法:

      public class Helper
      {
           private readonly Dictionary<string,bool> tmp = new Dictionary<string, bool>();
    
           public bool Condition(string item)
           {
               var parent = SemiExpensiveCallToGetParent(item);
               if (temp.TryGetValue(parent, out bool result))
                  return result;
               var matched = ExpensiveCallToCheckMatch(parent);
               temp.Add(parent, matched);
               return matched;
           }
        }
    

    你用这个来调用

        yourCollection.Where(new Helper().Condition);
    

    再次强调一下:它仅适用于实体的 LINQ,而不适用于 LINQ to SQL。

    并将您喜欢的 StringComparer 放入 Dictionary 的构造函数调用中。

    【讨论】:

      【解决方案2】:

      如果它与您的matches 变量在同一范围内可见,则无需将其传入即可使用它。如果在您调用Where() 之外定义了dynamicSet 变量,则只需使用@987654324 @。你不需要传递它。

      【讨论】:

        猜你喜欢
        • 2010-11-03
        • 1970-01-01
        • 2010-10-25
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多