【问题标题】:How can I Remove items from dictionary using lambda expression如何使用 lambda 表达式从字典中删除项目
【发布时间】:2011-08-02 09:28:35
【问题描述】:

我不喜欢 LINQ 解决方案,

我正在使用简单的谓词来确定是否应该删除密钥, 例如,如果字典的构造类似于Dictionary<int, int>, 那么我应该如何删除所有带有负面数据的条目

我更喜欢使用相同的字典,而不是创建新字典, 我没有性能问题

有没有办法做到这一点,不使用 LINQ,但使用 Lambda 表达式?

我不想要 LINQ 中的解决方案,因为没有人在我的项目中使用它们,不想成为第一个..,但是因为我看到 LINQ 解决方案看起来更好,所以我会使用它们..

【问题讨论】:

  • 键或值中的负数据?还是两者兼而有之?
  • 我认为在这种情况下你不能使用没有 linq 的 lambda 表达式

标签: c# dictionary lambda


【解决方案1】:

最简单的方法可能是创建一个 new 字典,如果你觉得这样的话:

var newDictionary = oldDictionary.Where(pair => pair.Value >= 0)
                                 .ToDictionary(pair => pair.Key,
                                               pair => pair.Value);

如果您必须改变现有字典(例如,因为几个其他对象引用了同一个字典),您需要构建一个要删除的键列表,然后再删除它们:

var toRemove = dictionary.Where(pair => pair.Value < 0)
                         .Select(pair => pair.Key)
                         .ToList();

foreach (var key in toRemove)
{
    dictionary.Remove(key);
}

编辑:我刚刚注意到第一句话:“我不喜欢 LINQ 解决方案”。如果这意味着您不想使用 LINQ 解决方案,这里是手动版本:

List<int> toRemove = new List<int>();
foreach (KeyValuePair<int, int> pair in dictionary)
{
    if (pair.Value < 0)
    {
        toRemove.Add(pair.Key);
    }
}

foreach (var key in toRemove)
{
    dictionary.Remove(key);
}

...但是如果您可以使用 LINQ,我鼓励您这样做。我的第二个解决方案相当于“手动”版本,但 IMO 更具可读性。

【讨论】:

  • 我应该添加哪个参考来支持“Where”关键字?
  • @Delashmate:添加对System.Core 的引用并添加using System.Linq;。这是假设您使用的是 .NET 3.5 或更高版本。
  • @Delashmate:我刚刚看到有人说你“不喜欢 LINQ 解决方案”——你的意思是你没有这些经验,或者你没有 想要 LINQ 解决方案?
  • @Delashmate:如果您项目中的每个人都采取这种态度,那么您将永远使用 LINQ。这里的 LINQ 解决方案不是更容易理解,更具声明性吗?我强烈建议您接受 LINQ - 这是一项了不起的技术。至少与你的队友讨论。
  • @Jon,我接受了你的建议 :)
【解决方案2】:

仅使用 lambda 表达式:

foreach (var i in myDict.Where(d => (d.Value  < 0 || d.key <0)).ToList() ) 
{
  myDict.Remove(i.Key);
}

【讨论】:

  • 这不会因为您在迭代集合时修改集合而中断吗?
  • ToList() 方法会创建一个克隆,因此您可以遍历一个克隆并从原始字典中删除
  • 哦,是的!我想如果没有ToList() 它会坏掉:)
【解决方案3】:
var toRemove = dict.Keys.Where(predicate).ToArray();
foreach (var key in toRemove) {
    dict.Remove(key);
}

【讨论】:

  • 请注意,ToList 通常比 ToArray 更有效。除非您需要一个数组,否则 ToList 是首选 IMO。
  • @Jon,不是我怀疑你,但为什么会这样?数组不是比列表更轻量级的结构吗?
  • @mikel:数组的大小必须完全正确。您通常构建“大”集合的方式是每次需要时将缓冲区大小加倍。这适用于一个列表,您可以在之后只使用超大缓冲区 - 但是如果您之后需要一个数组,您通常需要将缓冲区中的所有数据复制到一个 new 数组中合适的尺码。请参阅 msmvps.com/blogs/jon_skeet/archive/2011/01/02/… 了解 ToArray 的大致用途。
【解决方案4】:

如果你添加的话

namespace MMExtensions
{
    public static class DictionaryExtensions
    {
        public delegate bool Predicate<TKey, TValue>(KeyValuePair<TKey, TValue> d);

        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void Filter<TKey, TValue>(
            this Dictionary<TKey, TValue> hashtable, Predicate<TKey, TValue> p)
        {
            foreach (KeyValuePair<TKey, TValue> value in hashtable.ToList().Where(value => !p(value)))
                hashtable.Remove(value.Key);
        }
    }
}

你有一些数据集作为字典:

    Dictionary<string, int> d =
            new Dictionary<string, int> {{"v", -3}, {"val1", 1}, {"val2", 2}};

那么你可以使用:

    d.Filter(delegate(KeyValuePair<string, int> kv) { return kv.Value >= 0; });
    d.Filter(kv => kv.Value >= 0);// or as lambda

【讨论】:

  • 我认为你不需要MethodImplOptions.Synchronized这里
【解决方案5】:

您想从该词典中删除项目,还是愿意使用不包含这些项目的新词典?

var d = new Dictionary<int,int>();
var newDict = d.Where(entry => entry.Value >= 0).ToDictionary(entry => entry.Key, entry => entry.Value);

【讨论】:

    【解决方案6】:

    最简单的一个:

    Dictionary<long, long> dict...
    Dictionary<long, long> result = dict.Were(x => x.Value >= 0).ToDictionary(x => x.Key, x => x.Value);
    

    或者只是在“for”中以相反的顺序循环并删除无效的。

    【讨论】:

      【解决方案7】:

      我知道您说您不喜欢 Linq,但我无法通过以下解决方案控制自己,而且如果您阅读问题的标题,它仍然很有用。这可能是解决您的问题的最优雅的解决方案:

      dictionary.Where(pair => pair.Value < 0)
                .Select(pair => { 
                    dictionary.Remove(pair.Key);
                    return pair.Key;
                });
      

      【讨论】:

      • 而不是Select 使用Anyreturn false(或Allreturn true,更自然)
      猜你喜欢
      • 1970-01-01
      • 2012-08-31
      • 2012-02-21
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多