2017-10-04 24 views
5

Tôi có một lớp MyClasstập hợp các cặp khóa-giá trị nơi quan trọng phụ thuộc vào giá trị

class MyClass 
{ 
    public string Name { get; set; } // is unique among all instances 
    public SomeClass Data { get; set; } 
    ... 
} 

của mà tôi muốn lưu trữ một số trường hợp trong một bộ sưu tập. Tôi thường sẽ cần phải kiểm tra xem một cá thể có tên nào đó tồn tại không, và nếu có, hãy lấy lại cá thể đó. Vì việc lặp qua toàn bộ tập hợp không phải là một tùy chọn (hiệu suất!), Tôi đã nghĩ đến việc sử dụng tập hợp các cặp khóa-giá trị, ví dụ: an IDictionary<string, MyClass>.

Chương trình của tôi cũng sẽ cho phép đổi tên các phiên bản MyClass (nó sẽ không cho phép đổi tên nếu tính duy nhất của tên sẽ bị vi phạm). Nhưng nếu tôi đổi tên một MyClass, tôi cũng sẽ cần xóa mục cũ khỏi từ điển và thêm mục mới (tức là với tên mới) để giữ cho dữ liệu nhất quán.

Vấn đề là tôi sẽ có một số từ điển như vậy (chứa các tập con của tất cả các trường hợp MyClass) ở khắp mọi nơi, và sẽ khó theo dõi chúng và cập nhật thường xuyên tất cả các từ điển sau mỗi lần đổi tên.

Có cách nào để giữ các cặp khóa-giá trị nhất quán tự động không? Tôi nghĩ rằng tôi nghe nói về một cấu trúc dữ liệu cho phép điều này, mà tồn tại ít nhất trong C + + (không may, tôi không có ý tưởng làm thế nào nó được gọi là). Về cơ bản, nó phải là một bộ sưu tập mà khóa không chỉ là một chuỗi đơn giản mà còn giống như một tham chiếu đến một chuỗi (đến thuộc tính name trong trường hợp này), nhưng hoạt động như thể nó là một chuỗi. Liệu một điều như vậy tồn tại trong C#? Bạn có những ý tưởng khác làm thế nào để giữ cho các bộ sưu tập phù hợp?

Ý tưởng duy nhất của tôi là có một bộ sưu tập tất cả các từ điển ở mức cao nhất trong chương trình của tôi và làm cho phương pháp đổi tên cập nhật tất cả các từ điển đó sau quá trình đổi tên thực tế. Nhưng phải có một cách tốt hơn!


Tại sao câu hỏi này không phải là một bản sao của Best way to change dictionary key:

tôi đã biết rằng một cuốn từ điển không cho phép thay đổi chìa khóa. Thay vào đó, tôi yêu cầu một cấu trúc dữ liệu khác bằng cách nào đó tương thích với các thay đổi quan trọng (mà không làm mất lợi ích hiệu suất hoàn toàn), và tôi cũng yêu cầu các cách tiếp cận khác. Vì vậy, câu hỏi của tôi là nhiều hơn nữa mở để đầu vào từ bất kỳ hướng nào, miễn là nó giúp giải quyết vấn đề giữ dữ liệu phù hợp.

+1

Khi sử dụng từ điển (hoặc bất kỳ khóa-giá trị nào khác), bạn nên đảm bảo rằng các phím vẫn giữ nguyên. Lý do tại sao các bộ sưu tập đó nhanh chóng, là chúng sử dụng băm các phím, do đó nhiều khóa có thể được tìm thấy rất nhanh. Nếu bạn sửa đổi các giá trị được sử dụng trong hàm băm, bạn sẽ hoàn toàn mất chức năng băm và do đó hiệu suất đạt được – HimBromBeere

+0

Tôi không nghĩ rằng câu hỏi trùng lặp như đã nêu ở trên và sẽ đề xuất câu trả lời (không tương thích với câu trả lời được chỉ dẫn bởi liên kết trùng lặp) –

+0

hỏi lại và tôi sẽ trả lời –

Trả lời

2

Theo như tôi hiểu bạn, vấn đề của bạn là này:

  • bạn có nhiều từ điển, mỗi nắm giữ một phần của dữ liệu của bạn
  • Tất cả các trường hợp của bạn nên có một tên duy nhất trong suốt tất cả các từ điển
  • Khi một tên được thay đổi:
    • Thứ nhất, kiểm tra tên này vẫn là duy nhất
    • Cập nhật nó trong bất cứ dictionray nó sống ở

Tôi nghĩ rằng tôi sẽ giải quyết vấn đề này một chút khác nhau.

Trước tiên, hãy thêm trường ID vào lớp sẽ là số Hướng dẫn/chạy, Trường đó sẽ không bao giờ thay đổi từ thời điểm cá thể được tạo.
Tiếp theo, thêm một từ điển mà sẽ giữ chỉ tên và ID của các trường hợp, nó sẽ giống như thế này:

[{"FirstName": "Guid1"}, 
{"SecondName": "Guid2"}, 
{"ThirdName": "Guid3"}] 

Phần còn lại của bộ từ điển của bạn sẽ giữ ID là chìa khóa của họ, và không tên:

[{"Guid1": {instance1}}, 
{"Guid2": {instance2}}] 

Bây giờ khi bạn thay đổi tên của một cá thể, tất cả các tên tồn tại trong một từ điển duy nhất sẽ cho bạn biết nếu nó đã tồn tại. Và bạn cần phải thay đổi nó chỉ ở một nơi duy nhất, vì phần còn lại của các từ điển dựa vào một giá trị không đổi sẽ không bao giờ thay đổi.
Vì vậy, nói rằng bạn muốn thay đổi tên của "FirstName", từ điển tên sẽ trông như thế này:

[{"OtherName": "Guid1"}, 
{"SecondName": "Guid2"}, 
{"ThirdName": "Guid3"}] 

Và phần còn lại của dữ liệu không cần phải thay đổi.

1

Tôi không nghĩ rằng có một bộ sưu tập riêng để làm điều đó. Tuy nhiên bạn có thể dễ dàng tạo của riêng bạn bằng cách chỉ cần thêm một số loại thông báo trong lớp cơ sở của bạn.

public class ChangingNameObject 
    { 
     public delegate void ObjectNameChange(string oldName, string newName); 
     public event ObjectNameChange ObjectNameChanged; 
     private string name; 
     public string Name 
     { 
      get => name; 
      set 
      { 
       ObjectNameChanged?.Invoke(name, value); 
       name = value; 
      } 
     } 
    } 

    public class WatchingDictionary 
    { 
     private Dictionary<string, ChangingNameObject> content = new Dictionary<string, ChangingNameObject>(); 

     public void Add(ChangingNameObject item) 
     { 
      item.ObjectNameChanged += UpdatePosition; 
      content[item.Name] = item; 
     } 

     public void Remove(ChangingNameObject item) 
     { 
      item.ObjectNameChanged -= UpdatePosition; 
      content.Remove(item.Name); 
     } 

     private void UpdatePosition(string oldname, string newname) 
     { 
      var o = content[oldname]; 
      content.Remove(oldname); 
      content.Add(newname, o); 
     } 
    } 

Tôi chỉ viết những thứ rất cơ bản và bạn bỏ lỡ tất cả những người truy cập và điều tra viên, chỉ cần thêm người bạn cần.

Hãy rất cẩn thận với kiểu liệt kê mặc dù như thay đổi một bộ sưu tập trong liệt kê sẽ gây ra một thất bại (và như bộ sưu tập được ẩn, youu có thể làm việc đó mà không biết)

+1

Lớp trừu tượng 'KeyedCollection ' có thể là một bộ xương tốt để thực hiện điều này. – Kjara

+0

Có điểm tốt. Tôi không biết cái này. –

Các vấn đề liên quan