2013-03-25 11 views
5

Czy istnieje .NET analogowy z defaultdict Pythona? Uważam, że warto napisać krótki kod, np. Zliczanie częstotliwości:Analogicznie do defaultdict Pythona?

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

Więc najlepiej w C# mógłbym napisać:

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

Co oznacza 'defaultdict' zrobić ? Nie znam się na pythonie. Edycja: to tylko słownik, który ma domyślną wartość dla kluczy. Możesz podklasować 'Słownik' i zaimplementować funkcjonalność. – Romoku

+1

Odpowiedź Jona Skeeta może pomóc: http://stackoverflow.com/a/2601501/1786606. – Vladimir

Odpowiedz

4

nie sądzę istnieje odpowiednik, ale biorąc pod uwagę swój przykład można zrobić z LINQ:

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

Coś, od czego zaczniesz. Po prostu zmieniłem indeksator this. Ponieważ nie znam pełnej funkcjonalności Pythona defaultdict, nie mogę go dalej ulepszać. Twój podany przykład zadziała.

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

Oto proste wdrożenie:

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

A jak byś go używać:

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

Albo tak:

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