【问题标题】:When using a LINQ Where clause on a Dictionary, how can I return a dictionary of the same type?在 Dictionary 上使用 LINQ Where 子句时,如何返回相同类型的字典?
【发布时间】:2010-10-28 04:15:02
【问题描述】:

我目前正在使用以下代码来实现这一点,但似乎应该有更好的...建议?在我看来,应该有一种方法可以跳过 foreach...

Dictionary<string,string> getValidIds(Dictionary<string,string> SalesPersons,List<string> ids)
{
    Dictionary<string,string> o = new Dictionary<string,string>();
    var ie = SalesPersons.Where<KeyValuePair<string, string>>(t => ids.Contains(t.Key));
    foreach (var i in ie)
    {
        o.Add(i.Key, i.Value);
    }
    return o;
}

【问题讨论】:

    标签: c# linq optimization


    【解决方案1】:

    很确定您可以根据 Where 调用的结果调用 ToDictionary:

    Dictionary<string, string> GetValidIds(Dictionary<string, string> salesPersons,
        IList<string> ids)
    {
        return salesPersons
            .Where(p => ids.Contains(p.Key))
            .ToDictionary(p => p.Key, p => p.Value);
    }
    

    【讨论】:

    • +1,Marc,虽然我认为如果你担心这种东西的性能,那么你的内存就太多了! :)
    • @Matt... 好吧,也许 - 但有一点是 O(1)/O(Nlog(N)) *不是 不合理的,但是O(N^2) 个问题——当然是1k、10k还是100k取决于具体的过程。
    【解决方案2】:

    有趣的是,如果您首先枚举字典(长度 N) 并检查列表(长度 M)是否包含,那么您将获得 O(NM) 性能。

    您可以构建一个 HashSet&lt;&gt; 的 id,但这似乎是多余的,因为我们已经有一个(预散列的)字典可用。

    我会先遍历 id;因为字典查找(按键)是 O(1),这提供了 O(M) 性能 - 然而,这可能意味着您不使用 LINQ(因为TryGetValue 不会喜欢 LINQ(并且引入元组是太喜欢努力工作了)...

        Dictionary<string, string> getValidIds(
                IDictionary<string, string> salesPersons,
                IEnumerable<string> ids) {
            var result = new Dictionary<string, string>();
            string value;
            foreach (string key in ids) {
                if (salesPersons.TryGetValue(key, out value)) {
                    result.Add(key, value);
                }
            }
            return result;
        }
    

    我并不担心这比 LINQ 版本多行;它消除了 O(N) 的复杂性...


    编辑;以下 可能 工作(我还没有测试过),但我认为这是对 LINQ 的滥用,并且肯定不会扩展到 PLINQ 等......请谨慎使用!我也相信foreach 方法的开销更少,所以会更快......无论如何:

        Dictionary<string, string> getValidIds(
            IDictionary<string, string> salesPersons,
            IEnumerable<string> ids)
        {
            string value = null;
            return  (from key in ids
                    where salesPersons.TryGetValue(key, out value) // HACK: v. dodgy
                    select new { key, value })
                    .ToDictionary(x=>x.key, x=>x.value);
        }
    

    【讨论】:

      【解决方案3】:

      似乎对在列表中查找内容大惊小怪。如果列表只包含几个元素,那么没什么大不了的。如果 List 包含数千个元素,您将需要 O(1) 对其进行查找。 HashSet 可以提供这个。

      Dictionary<string, string> getValidIds(
        Dictionary<string, string> SalesPersons,
        List<string> ids
      )
      {
        HashSet<string> idsFast = new HashSet<string>(ids);
        Dictionary<string, string> result = SalesPersons
          .Where(kvp => idsFast.Contains(kvp.Key))
          .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
        return result;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-18
        • 2020-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多