我有一本字典。对象的相同实例可以分布在多个键上。我正在编写一个方法,以便您可以传递实例,并且将删除该实例的所有键。
以下作品,但我对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;
}
答案 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