【问题标题】:Remove all items that match a condition in IDictionary删除与 IDictionary 中的条件匹配的所有项目
【发布时间】:2014-06-28 12:28:51
【问题描述】:

我正在尝试删除 IDictionary 对象中与条件匹配的所有元素。

例如IDictionary 包含一组键和相应的值(比如说 80 个对象)。键是字符串,值可以是不同的类型(想想使用 directshow 从 wtv 文件中提取元数据)。

某些键包含文本“thumb”,例如拇指大小,开始拇指日期等。 我想从 IDictionary 中删除所有包含单词 thumb 的对象。

我在这里看到的唯一方法是使用 .Remove 方法手动指定每个键名。

有什么方法可以让所有键中包含 thumb 的对象,然后将它们从 IDictionary 对象中删除。

代码如下所示:

IDictionary sourceAttrs = editor.GetAttributes();

GetAttributes 定义为:

public abstract IDictionary GetAttributes();

我无法控制 GetAttributes,它返回一个 IDictionary 对象,我只能在调试时查看它的内容。 (可能是哈希表)

更新:感谢蒂姆的最终答案:

sourceAttrs = sourceAttrs.Keys.Cast<string>()
                 .Where(key => key.IndexOf("thumb", StringComparison.CurrentCultureIgnoreCase) == -1)
                 .ToDictionary(key => key, key => sourceAttrs[key]);

【问题讨论】:

  • 真实类型是什么?如果它实际上是一个通用字典,你可以简单地转换它。您可以通过as 运算符尝试投射它。例如:var dict = sourceAttrs as Dictionary&lt;string, object&gt;。如果演员表不起作用,则为 null。
  • 不知道,看起来像一个带有 的哈希表
  • 请不要在问题标题中包含有关所用语言的信息,除非没有它就没有意义。标记用于此目的。
  • 知道了,谢谢日后参考

标签: c# match idictionary


【解决方案1】:

因此,您要删除键包含子字符串的所有条目。

您可以通过保留所有包含它的内容来使用 LINQ:

dict = dict
  .Where(kv => !kv.Key.Contains("thumb"))
  .ToDictionary(kv => kv.Key, kv => kv.Value);

如果你想要一个不区分大小写的比较,你可以使用IndexOf:

dict = dict
  .Where(kv => kv.Key.IndexOf("thumb", StringComparison.CurrentCultureIgnoreCase) == -1)
  .ToDictionary(kv => kv.Key, kv => kv.Value);

更新根据您的非通用编辑:

如果它是像 HashTable 这样的非通用字典,则不能直接使用 LINQ,但如果您知道键是 string,则可以使用以下查询:

// sample IDictionary with an old Hashtable
System.Collections.IDictionary sourceAttrs = new System.Collections.Hashtable
{ 
    {"athumB", "foo1"},
    {"other", "foo2"}
};

Dictionary<string, object> newGenericDict = sourceAttrs.Keys.Cast<string>()
    .Where(key => !key.Contains("thumb"))
    .ToDictionary(key => key, key => sourceAttrs[key]);

但也许它实际上是一个通用的Dictionary,你可以尝试使用as 运算符:

var dict = sourceAttrs as Dictionary<string, object>;

如果演员表不起作用,则为 null。

【讨论】:

  • 我不使用带有 IDictionary 对象的 Where 方法(我已包含 system.linq 并使用 .net4 客户端框架)
  • @rboy:你需要像IDictionary&lt;string, object&gt; dict = new Dictionary&lt;string, object&gt;()这样的通用字典
  • 我将编辑问题以添加更多详细信息,我不知道 IDictionary 包含什么。它通过一个抽象接口返回给我。
  • 谢谢,拇指会不区分大小写吗?
  • 为什么不使用:sourceAttrs = sourceAttrs.Keys.Cast() .Where(key => !key.ToLower().Contains("thumb")) .ToDictionary(key => key, key => sourceAttrs[key]);
【解决方案2】:

如果你的字典是只读的,你需要一个一个地删除,在这种情况下你也可以使用 LINQ:

dict
  .Keys
  .Where(p => p.Contains("thumb"))
  .ToList
  .ForEach(p => dict.Remove(p);

请注意,这是有效的,因为在删除时您不再循环遍历字典:您首先完全循环遍历字典以构建要删除的键列表,然后遍历此列表并重新访问字典以删除键一个接一个。

如果您的字典不是只读的并且效率是一个问题,那么您最好听听 Tim 的建议。

【讨论】:

    猜你喜欢
    • 2017-01-27
    • 2012-12-04
    • 2017-03-18
    • 1970-01-01
    • 2019-09-06
    • 2017-12-20
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多