从多值字典中删除特定值

时间:2012-10-17 03:29:22

标签: c# collections dictionary

我在这里看过有关如何制作每个键具有多个值的字典的帖子,例如此链接中提供的解决方案之一:

Multi Value Dictionary

似乎我必须使用List<>作为键的值,以便键可以存储多个值。

如果要添加值,链接中的解决方案就可以了。但我现在的问题是如何从单个键中删除特定值。

我有这个代码用于向字典添加值:

private Dictionary<TKey, List<TValue>> mEventDict;
    // this is for initializing the dictionary


public void Subscribe(eVtEvtId inEvent, VtEvtDelegate inCallbackMethod)
    {
        if (mEventDict.ContainsKey(inEvent))
        {
            mEventDict[inEvent].Add(inCallbackMethod);
        }
        else
        {
            mEventDict.Add(inEvent, new List<TValue>() { v });
        }
    }
// this is for adding values to the dictionary.
// if the "key" (inEvent) is not yet present in the dictionary,
// the key will be added first before the value

我现在的问题是从密钥中删除特定值。我有这段代码:

public void Unsubscribe(eVtEvtId inEvent, VtEvtDelegate inCallbackMethod)
    {
        try
        {
            mEventDict[inEvent].Remove(inCallbackMethod);
        }

        catch (ArgumentNullException)
        {
            MessageBox.Show("The event is not yet present in the dictionary");
        }
    }
基本上,我所做的只是用Add()替换Add()。这有用吗?

此外,如果您对代码有任何问题或疑问(初始化等),请随时询问。

感谢您的建议。

3 个答案:

答案 0 :(得分:2)

TylerOhlsen的回答是向正确方向迈出的一步,但它有6个键查找(调用Remove,ContainsKey和索引器)。使用TryGetValue可以将其减少到三个:

private Dictionary<TKey, List<TValue>> mEventDict;

public void Subscribe(TKey inEvent, TValue inCallbackMethod)
{
    List<TValue> list;

    if (mEventDict.TryGetValue(inEvent, out list))
        list.Add(inCallbackMethod);
    else
        mEventDict.Add(inEvent, new List<TValue> { inCallbackMethod });
}

public bool Unsubscribe(TKey inEvent, TValue inCallbackMethod)
{
    List<TValue> list;

    if (!mEventDict.TryGetValue(inEvent, out list))
        return false;

    bool removed = list.Remove(inCallbackMethod);

    if (list.Count == 0)
        mEventDict.Remove(inEvent);

    return removed;
}

如果您不关心删除空列表:

public bool Unsubscribe(TKey inEvent, TValue inCallbackMethod)
{
    List<TValue> list;

    if (!mEventDict.TryGetValue(inEvent, out list))
        return false;

    return list.Remove(inCallbackMethod);
}

如果您不需要报告项目是否在列表中(并因此从中删除),请将返回类型更改为void,并(在第一个版本中)删除removed变量

答案 1 :(得分:1)

会起作用吗?不完全是你想要的......

  • 您的方法参数必须是通用类型。
  • List(T).Remove不会抛出ArgumentNullException。
  • 如果列表变空,您可能需要清理字典。
  • 调用者可能不在乎在取消订阅时是否订阅了回调,但是您有这些信息,所以您也可以将其返回。此信息可能有助于排除故障/记录日志。

这是我建议的......

private Dictionary<TKey, List<TValue>> mEventDict;

public void Subscribe(TKey inEvent, TValue inCallbackMethod)
{
    if (!mEventDict.ContainsKey(inEvent))
        mEventDict.Add(inEvent, new List<TValue>());

    mEventDict[inEvent].Add(inCallbackMethod);
}

public bool Unsubscribe(TKey inEvent, TValue inCallbackMethod)
{
    if (!mEventDict.ContainsKey(inEvent))
        return false;

    bool removed = mEventDict[inEvent].Remove(inCallbackMethod);

    if (mEventDict[inEvent].Count == 0)
        mEventDict.Remove(inEvent);

    return removed;
}

注意:我没有测试过这段代码,所以试试吧。此外,此代码线程安全。

答案 2 :(得分:0)

@phoog - 所以我想将Unsubscribe方法保留为void。在修改代码之后,这就是我想出来的......

public void Unsubscribe(TKey inEvent, TValue inCallbackMethod)
{
    List<TValue> list;

    bool mRemoved = false.

    if (mEventDict.TryGetValue(inEvent, out list))
    {
        list.Remove(inCallbackMethod);
        mRemoved = true;
    }
}

是必需的listRemoved变量吗?但话说回来,如果在列表中找不到inCallbackMethod,我认为不会发生任何事情。