类似于python的defaultdict
本文关键字:defaultdict python 类似于 | 更新日期: 2023-09-27 18:05:53
是否有。net类似于Python的defaultdict
?我发现编写简短的代码很有用,例如:计数频率:
>>> words = "to be or not to be".split()
>>> print words
['to', 'be', 'or', 'not', 'to', 'be']
>>> from collections import defaultdict
>>> frequencies = defaultdict(int)
>>> for word in words:
... frequencies[word] += 1
...
>>> print frequencies
defaultdict(<type 'int'>, {'not': 1, 'to': 2, 'or': 1, 'be': 2})
所以理想情况下,我可以在c#中写:
var frequencies = new DefaultDictionary<string,int>(() => 0);
foreach(string word in words)
{
frequencies[word] += 1
}
下面是一个简单的实现:
public class DefaultDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : new()
{
public new TValue this[TKey key]
{
get
{
TValue val;
if (!TryGetValue(key, out val))
{
val = new TValue();
Add(key, val);
}
return val;
}
set { base[key] = value; }
}
}
如何使用:
var dict = new DefaultDictionary<string, int>();
Debug.WriteLine(dict["foo"]); // prints "0"
dict["bar"] = 5;
Debug.WriteLine(dict["bar"]); // prints "5"
或者像这样:
var dict = new DefaultDictionary<string, List<int>>();
dict["foo"].Add(1);
dict["foo"].Add(2);
dict["foo"].Add(3);
让你开始。我只是改变了this
索引器。由于我不知道python的defaultdict
的完整功能,我无法进一步改进它。您给出的例子将工作。
public class DefaultDictionary<TKey, TValue> : IDictionary<TKey,TValue>
{
private readonly Func<TValue> _defaultSelector;
private readonly Dictionary<TKey, TValue> _values = new Dictionary<TKey, TValue>();
public DefaultDictionary()
: this(() => default(TValue))
{
}
public DefaultDictionary(Func<TValue> defaultSelector)
{
_defaultSelector = defaultSelector;
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
return _values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(KeyValuePair<TKey, TValue> item)
{
((IDictionary<TKey,TValue>)_values).Add(item);
}
public void Clear()
{
_values.Clear();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return ((IDictionary<TKey,TValue>)_values).Contains(item);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
((IDictionary<TKey, TValue>)_values).CopyTo(array, arrayIndex);
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return ((IDictionary<TKey, TValue>)_values).Remove(item);
}
public int Count { get { return _values.Count; } }
public bool IsReadOnly { get { return ((IDictionary<TKey, TValue>) _values).IsReadOnly; } }
public bool ContainsKey(TKey key)
{
return _values.ContainsKey(key);
}
public void Add(TKey key, TValue value)
{
_values.Add(key, value);
}
public bool Remove(TKey key)
{
return _values.Remove(key);
}
public bool TryGetValue(TKey key, out TValue value)
{
return _values.TryGetValue(key, out value);
}
public TValue this[TKey key]
{
get
{
if (!_values.ContainsKey(key))
{
_values.Add(key, _defaultSelector());
}
return _values[key];
}
set
{
if(!_values.ContainsKey(key))
{
_values.Add(key, _defaultSelector());
}
_values[key] = value;
}
}
public ICollection<TKey> Keys { get { return _values.Keys; } }
public ICollection<TValue> Values { get { return _values.Values; } }
public Dictionary<TKey, TValue> ToDictionary()
{
return new Dictionary<TKey, TValue>(_values);
}
}
我不认为有一个等效的,但根据您的示例,您可以使用LINQ:
var words = new List<string>{ "One", "Two", "Three", "One" };
var frequencies = words.GroupBy (w => w).ToDictionary (w => w.Key, w => w.Count());
ConcurrentDictionary(在System.Collections.Generic中)的行为非常相似(尽管是为并发使用设计的)
-
检索值:GetOrAdd方法返回键的值,如果键不存在,则使用值工厂创建一个键。
-
设置值:AddOrUpdate方法更新一个值,或者在该值不存在时设置它
优势:
- 线程安全的
- 完全控制默认值和更新步骤
缺点:
- 语法略冗长