我有以下代码:
class MyClass
{
string Name;
int NewInfo;
}
List<MyClass> newInfo = .... // initialize list with some values
Dictionary<string, int> myDict = .... // initialize dictionary with some values
foreach(var item in newInfo)
{
if(myDict.ContainsKey(item.Name)) // 'A' I hash the first time here
myDict[item.Name] += item.NewInfo // 'B' I hash the second (and third?) time here
else
myDict.Add(item.Name, item.NewInfo);
}
Run Code Online (Sandbox Code Playgroud)
有没有办法避免在字典中进行两次查找 - 第一次查看是否包含条目,第二次更新值?在'B'行上甚至可能有两个哈希查找 - 一个用于获取int值,另一个用于更新它.
Jon*_*eet 14
是的 - 使用Dictionary.TryGetValue.它接受一个out参数来接收值,并返回是否找到该值.这是您调整后的代码:
foreach(var item in newInfo)
{
int value;
if (myDict.TryGetValue(item.Name, out value))
{
myDict[item.Name] = value + item.NewInfo;
}
else
{
myDict[item.Name] = item.NewInfo;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,在这种特殊情况下,我们可以做得更好.如果键- 没有找到,out因为我们要设定新的价值无论是参数设置为0 item.NewInfo或item.NewInfo + value我们真的做着同样的事情正在无论哪种方式.我们可以忽略方法的返回值,只需使用:
foreach(var item in newInfo)
{
int value;
myDict.TryGetValue(item.Name, out value);
myDict[item.Name] = value + item.NewInfo;
}
Run Code Online (Sandbox Code Playgroud)
这很不寻常 - 通常你会使用返回值.
插话
这只是因为你真的做了一个有效的GetValueOrDefault操作.实际上,这将是一对有效的扩展方法:
public static TValue GetValueOrDefault<TKey, TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key)
{
TValue value;
dictionary.TryGetValue(key, out value);
return value;
}
public static TValue GetValueOrDefault<TKey, TValue>
(this IDictionary<TKey, TValue> dictionary, TKey key,
TValue customDefault)
{
TValue value;
if (dictionary.TryGetValue(key, out value))
{
return value;
}
else
{
return customDefault;
}
}
Run Code Online (Sandbox Code Playgroud)
在这一点上,你可以让你的代码清晰和简洁:
foreach(var item in newInfo)
{
myDict[item.Name] = myDict.GetValueOrDefault(item.Name) + item.NewInfo;
}
Run Code Online (Sandbox Code Playgroud)
(你可以要求GetValueOrDefault(item.Name, 0)更清晰.)
回到这一点......
请注意,您仍在进行两次查找 - 一次用于获取值,另一次用于添加/替换它.如果不使TValue类型参数变得可变,你就无法避免这种情况,你可以在适当的位置进行更改.那是可能的,但不是非常好.
在原始代码中,您可能会进行三次查找 - 一次查找ContainsKey,然后两次(如果找到密钥)则替换该值.如果我们扩展以下内容,则更容易看到+=:
myDict[item.Name] = myDict[item.Name] + item.NewInfo;
Run Code Online (Sandbox Code Playgroud)
(item.Name只会被评估一次,但除此之外它是相同的.)
另一个题外话
最好有一个Dictionary基于函数进行"查找和替换"的操作,以获得基于旧值的新值,例如
bool Update(TKey key, Func<TValue, bool, TValue> replacementFunction)
Run Code Online (Sandbox Code Playgroud)
其中replacementFunction将采取的电流值(或默认值的函数TValue,如果键没有被发现)和布尔说的键是否被真正发现,并返回新值.然后字典可以查找密钥,调用替换函数并更新值.(这个不能作为扩展方法实现.)
| 归档时间: |
|
| 查看次数: |
438 次 |
| 最近记录: |