从IDictionary中删除所有符合条件的项

9

我试图删除所有符合条件的IDictionary对象中的元素。

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

其中一些键包含文本“thumb”,例如thumbsize,startthumbdate等。 我想从IDictionary中删除所有键包含单词thumb的对象。

我唯一能想到的方法是手动使用.Remove方法指定每个键名。

是否有一种方法可以获取所有键包含单词thumb的对象并将它们从IDictionary对象中删除?

代码如下:

IDictionary sourceAttrs = editor.GetAttributes();

GetAttributes的定义如下:

public abstract IDictionary GetAttributes();

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

更新:感谢Tim给出的最终答案:

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<string, object>。如果转换失败,则为 null。 - Tim Schmelter
不知道,看起来像是一个带有<string, object>的哈希表。 - rboy
请不要在问题标题中包含有关所使用编程语言的信息,除非没有它就没有意义。标签可以起到这个作用。 - Ondrej Janacek
明白了,谢谢,以备将来参考。 - rboy
2个回答

13

如果您想要删除所有键包含子字符串的条目。

您可以使用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
@rboy:你需要一个通用的字典,像这样 IDictionary<string, object> dict = new Dictionary<string, object>() - Tim Schmelter
我将编辑问题以添加更多细节,我不知道IDictionary包含什么。它是由一个抽象接口返回给我的。 - rboy
感谢您,那么对于拇指大小写不敏感吗? - rboy
为什么不使用:sourceAttrs = sourceAttrs.Keys.Cast<string>() .Where(key => !key.ToLower().Contains("thumb")) .ToDictionary(key => key, key => sourceAttrs[key]); - rboy
谢谢,我已经更新了答案,请告诉我现在是否是正确的答案。 - rboy

2

如果您的字典是只读的,那么您需要逐个删除其中的项,此时您也可以使用LINQ:

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

请注意,这种方法的有效性在于删除时不再遍历字典:首先完全遍历字典以建立一个要删除的键列表,然后遍历此列表并重新访问字典以逐个删除键。
如果您的字典不是只读的,并且效率是一个问题,那么最好使用Tim的建议。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接