2013-09-26 209 views
8

Đây là cách tôi sẽ tạo một Từ điển trong C#.Một thư viện như bộ sưu tập của Python. Thư viện trưng bày cho C# -> Lấy sự khác biệt về giá trị giữa hai đối tượng từ điển trong C#

Dictionary<string, int> d = new Dictionary<string, int>() 
    { 
     {"cheese", 2}, 
     {"cakes", 1}, 
     {"milk", 0}, 
     {"humans", -1} // This one's for laughs 
    }; 

Trong Python nếu bạn có một cuốn từ điển như vậy:

from collections import Counter 

my_first_dict = { 
    "cheese": 1, 
    "cakes": 2, 
    "milk": 3, 
} 

my_second_dict = { 
    "cheese": 0, 
    "cakes": 1, 
    "milk": 4, 
} 

print Counter(my_first_dict) - Counter(my_second_dict) 

>>> Counter({'cheese': 1, 'cakes': 1}) 

Như bạn thấy, Counter là rất hữu ích khi so sánh đối tượng từ điển.

Có thư viện nào trong C#, điều đó sẽ cho phép tôi làm điều gì đó tương tự như vậy hay tôi phải mã hóa từ đầu?

+0

AFAIK không có điều gì trong .NET. –

+0

Tôi chắc chắn bạn có thể bằng cách nào đó với LINQ – Quintium

+0

Không sử dụng Từ điển cho mọi thứ. C# là một ngôn ngữ được đánh máy mạnh. Tạo một mô hình dữ liệu thích hợp và sử dụng LINQ để truy vấn các bộ sưu tập của bạn và nhận bất kỳ kết quả hoặc phép chiếu nào bạn muốn. –

Trả lời

4

Bạn có thể tham gia hai bộ từ điển với nhau và sau đó tạo một hình mới dựa trên các hoạt động trao với chỉ một vài dòng mã:

Dictionary<string, int> d1 = new Dictionary<string, int>(); 
Dictionary<string, int> d2 = new Dictionary<string, int>(); 

var difference = d1.Join(d2, pair => pair.Key, pair => pair.Key, (a, b) => new 
{ 
    Key = a.Key, 
    Value = a.Value - b.Value, 
}) 
.Where(pair => pair.Value > 0) 
.ToDictionary(pair => pair.Key, pair => pair.Value); 

không có lớp hệ thống mà bạn đã chỉ ra rằng kết thúc tốt đẹp một một cuốn từ điển cung cấp một nhà điều hành - cho họ, nhưng bạn có thể làm của riêng bạn nếu bạn muốn một cách dễ dàng đủ:

public class Counter<T> : IEnumerable<KeyValuePair<T, int>> 
{ 
    private IEnumerable<KeyValuePair<T, int>> sequence; 
    public Counter(IEnumerable<KeyValuePair<T, int>> sequence) 
    { 
     this.sequence = sequence; 
    } 

    public static Counter<T> operator -(Counter<T> first, Counter<T> second) 
    { 
     return new Counter<T>(first.Join(second 
      , pair => pair.Key, pair => pair.Key, (a, b) => 
       new KeyValuePair<T, int>(a.Key, a.Value - b.Value)) 
      .Where(pair => pair.Value > 0)); 
    } 

    public IEnumerator<KeyValuePair<T, int>> GetEnumerator() 
    { 
     return sequence.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 
+0

Câu trả lời hay, bạn đã tạo toàn bộ lớp Counter. –

+0

Cảm ơn bạn. Tôi đánh giá cao sự giúp đỡ vô cùng. –

2

Không có tích hợp chức năng như thế này, nhưng bạn có thể sử dụng một chút LINQ:

Dictionary<string, int> first = new Dictionary<string, int>() 
{ 
    {"cheese", 1}, 
    {"cakes", 2}, 
    {"milk", 3}, 
}; 
Dictionary<string, int> second = new Dictionary<string, int>() 
{ 
    {"cheese", 0}, 
    {"cakes", 1}, 
    {"milk", 4}, 
}; 

var results = 
    (from x in first 
    join y in second on x.Key equals y.Key 
    where x.Value - y.Value > 0 
    select new { x.Key, Value = x.Value - y.Value }) 
    .ToDictionary(p => p.Key, p => p.Value); 

// returns a dictionary like { { "cheese", 1 }, { "cakes", 1 } } 
+0

'Where' là không cần thiết. Nếu giá trị bằng 0, thì đó chỉ đơn giản là kết quả phép trừ. – Servy

+0

@Servy Vâng trong ví dụ của OP, đối tượng kết quả không chứa một bản ghi cho "sữa". Tôi cho rằng đó là ý định ở đây. –

+0

@ p.s.w.g Có. Đó là ý định của tôi. –