2013-03-25 17 views
5

Esiste un analogo .NET di Python defaultdict? Trovo utile scrivere un codice breve, ad es. frequenze di conteggio:Defaultdict dell'analogue of Python?

>>> 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}) 

Quindi, idealmente in C# ho potuto scrivere:

var frequencies = new DefaultDictionary<string,int>(() => 0); 
foreach(string word in words) 
{ 
    frequencies[word] += 1 
} 
+2

Cosa significa il 'defaultdict' fare ? Non ho familiarità con Python. Modifica: è solo un dizionario che ha un valore predefinito per le chiavi. È possibile sottoclasse 'Dictionary' e implementare la funzionalità. – Romoku

+1

La risposta di Jon Skeet può aiutare: http://stackoverflow.com/a/2601501/1786606. – Vladimir

risposta

4

Io non credo che ci sia un equivalente, ma dato il tuo esempio si potrebbe fare questo con LINQ:

var words = new List<string>{ "One", "Two", "Three", "One" }; 
var frequencies = words.GroupBy (w => w).ToDictionary (w => w.Key, w => w.Count()); 
3

Qualcosa per iniziare. Fondamentalmente ho appena cambiato l'indicizzatore this. Dal momento che non conosco la funzionalità completa di Python defaultdict non riesco a migliorarlo ulteriormente. Il tuo esempio dato funzionerà.

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(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); 
    } 
} 
3

Ecco una semplice implementazione:

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; } 
    } 
} 

E come lo si dovrebbe utilizzare:

var dict = new DefaultDictionary<string, int>(); 
Debug.WriteLine(dict["foo"]); // prints "0" 
dict["bar"] = 5; 
Debug.WriteLine(dict["bar"]); // prints "5" 

O come questa:

var dict = new DefaultDictionary<string, List<int>>(); 
dict["foo"].Add(1); 
dict["foo"].Add(2); 
dict["foo"].Add(3);