从Dictionary中删除所有实例的最佳方法是什么?

时间:2016-05-05 19:35:38

标签: c# linq dictionary

我有一本字典。对象的相同实例可以分布在多个键上。我正在编写一个方法,以便您可以传递实例,并且将删除该实例的所有键。

以下作品,但我对Linq很弱。有更好的方法吗?我对优雅的代码感兴趣,但我更专注于速度。如何使此代码运行得更快(无需删除删除是否成功)?

/// <summary>
/// Removes obstacle from the level, and returns true if the removal was successful
/// </summary>
public bool Remove(Obstacle obstacle)
{
    if (!obstacleMap.ContainsValue(obstacle))
    {
        return false;
    }
    foreach (var key in obstacleMap.Keys.Where(k => obstacleMap[k] == obstacle))
    {
        obstacleMap.Remove(key);
    }
    return true;
}

4 个答案:

答案 0 :(得分:2)

这是一种更有效的方法,这也可以避免在枚举项目时从字典中删除项目时出现异常:

public bool Remove(Obstacle obstacle)
{
    var removeKeys = obstacleMap.Where(e => e.Value == obstacle).Select(e => e.Key).ToList();
    foreach (var key in removeKeys) obstacleMap.Remove(key);
    return removeKeys.Count > 0;
}

答案 1 :(得分:0)

最快的方法可能是创建第二个字典,其中障碍物对象作为键,值将是第一个字典中引用该对象的键列表。

现在设置词典的方式,它不适合您在Remove()方法中尝试做的事情。密钥查找比值查找快得多。

List<TKey> keys;
if (dict2.TryGetValue(obstacle, out keys))
{
    foreach (TKey key in keys)
    {
        obstacleMap.Remove(key);
    }

    dict2.Remove(obstacle);
}

请记住在添加障碍物时更新这两个词典。

答案 2 :(得分:0)

试试这个:

而不是:

foreach (var key in obstacleMap.Keys.Where(k => obstacleMap[k] == obstacle))
{
    obstacleMap.Remove(key);
}

使用此:

 var fObstacleMap = obstacleMap.Where(x => x.Value != obstacle).ToDictionary(y => y.Key, y => y.Value);

这会创建另一个没有障碍物参数传递的对象的字典,并且不会抛出异常。

答案 3 :(得分:0)

您也可以使用分组。不确定哪个性能更高。

var newDictionary = dictionary.GroupBy(_ => _.Value)
                              .Where(_ => _.Key != valueToRemove)
                              .ToDictionary(_=> _.Single(), _ => _.Key);

DotNetFiddle:https://dotnetfiddle.net/gRgCeX