2015-12-11 18 views
8

Có bất kỳ cấu trúc cho phép CẢ của các hoạt động này:độc đáo lấy chìa khoá-giá trị cặp

  • collection.TryGetValue(TKey, out TValue)
  • collection.TryGetKey(TValue, out TKey)

Trong một thời gian tốt hơn so với O (n)?

Vấn đề của tôi:

tôi về cơ bản cần để có thể lấy giá trị chủ chốt của hoặc giá trị của chính thực sự nhanh chóng, mà không cần sao chép bộ nhớ (vì vậy hai bộ từ điển là ra khỏi câu hỏi).

Lưu ý rất quan trọng: tất cả các phím là duy nhất và tất cả các giá trị là duy nhất. Có thông tin này, tôi cảm thấy bạn có thể thực hiện tác vụ này trong thời gian tốt hơn chỉ O (1) cho .TryGetValue và O (n) cho .TryGetKey.

EDIT:

Trong trường hợp của tôi, tôi có một ánh xạ giữa stringsints. Có ~ 650.000 cặp khóa-giá trị văn bản và ID của chúng. Vì vậy, về cơ bản tôi muốn nhận được chuỗi với một ID cụ thể mà còn là ID của một chuỗi nhất định.

+0

"mà không cần sao chép bộ nhớ (do đó, hai từ điển không hoạt động)". sử dụng hai bộ từ điển không lặp lại bộ nhớ trừ khi 'TKey' và' TValue' của bạn là cả hai cấu trúc. –

+0

@ScottChamberlain cả hai đều là cấu trúc :) –

+0

Tôi không biết liệu bạn có thể yêu cầu gì không. Ý tôi là, tôi không biết nhiều và vẫn còn nhiều điều để học nhưng một điều tôi luôn nghe về khoa học máy tính là: "Bạn muốn nó nhanh không? Bạn cần bộ nhớ. Bạn muốn nó sáng? Nó sẽ chậm hơn." Nhưng tôi ủng hộ câu hỏi của bạn kể từ khi tôi đang intresed. –

Trả lời

-2

bạn có thể làm điều đó;

Dictionary<string, string> types = new Dictionary<string, string>() 
      { 
         {"1", "one"}, 
         {"2", "two"}, 
         {"3", "three"} 
      }; 

      var myValue = types.FirstOrDefault(x => x.Value == "one").Key; 
+3

'Từ điển . BeforeOrDefault()' là 'O (n)', không phải 'O (1)'. – CodeCaster

+1

Tôi không biết liệu nhận xét đó có phải là câu trả lời của tôi hay không, nhưng hãy xem [Wikipedia: Ký hiệu Big O] (https://en.wikipedia.org/wiki/Big_O_notation). – CodeCaster

+0

xin lỗi xấu của tôi, đọc sai – Ktt

0

Bạn có thể viết một số wrapper cho key mà nên chứa chìa khóa và liên kết đến value wrapper và wrapper cho value mà nên chứa giá trị và liên kết đến key wrapper. Và sử dụng hai khác nhau HashSet s.
Trong trường hợp này, bạn tránh sao chép bộ nhớ. Bạn chỉ cần thêm bộ nhớ cho các liên kết.

3

Để tốt hơn O (n), bạn sẽ cần sử dụng từ điển thứ hai. Tuy nhiên như bạn đã đề cập bạn đang sử dụng cấu trúc và lo ngại về việc sử dụng bộ nhớ với từ điển thứ 2 có bản sao của cấu trúc.

Một cách xung quanh đây là hộp giá trị cấu trúc bên trong một đối tượng sau đó chia sẻ đối tượng được đóng hộp trong hai từ điển. Nếu bạn sử dụng kế thừa từ DictionaryBase, điều này thực sự khá dễ thực hiện.

public sealed class TwoWayDictionary<TKey, TValue> : DictionaryBase 
{ 
    Hashtable reverseLookup = new Hashtable(); 

    public void Add(TKey key, TValue value) 
    { 
     this.Dictionary.Add(key, value); 
    } 

    public void Remove(TKey key) 
    { 
     this.Dictionary.Remove(key); 
    } 

    public bool TryGetValue(TKey key, out TValue value) 
    { 
     object lookup = Dictionary[key]; 
     if (lookup == null) 
     { 
      value = default(TValue); 
      return false; 
     } 
     else 
     { 
      value = (TValue)lookup; 
      return true; 
     } 
    } 

    public bool TryGetKey(TValue value, out TKey key) 
    { 
     object lookup = reverseLookup[value]; 
     if (lookup == null) 
     { 
      key = default(TKey); 
      return false; 
     } 
     else 
     { 
      key = (TKey)lookup; 
      return true; 
     } 
    } 

    //If OnInsertComplete or OnSetComplete raises a exception DictionaryBase will 
    // roll back the operation it completed. 
    protected override void OnInsertComplete(object key, object value) 
    { 
     reverseLookup.Add(value, key); 
    } 

    protected override void OnSetComplete(object key, object oldValue, object newValue) 
    { 
     if(reverseLookup.Contains(newValue)) 
      throw new InvalidOperationException("Duplicate value"); 
     if(oldValue != null) 
      reverseLookup.Remove(oldValue); 
     reverseLookup[newValue] = key; 
    } 

    protected override void OnRemoveComplete(object key, object value) 
    { 
     reverseLookup.Remove(value); 
    } 
} 

Các DictionaryreverseLookup từ điển sẽ chia sẻ các tài liệu tham khảo tương tự như vậy nó sẽ có một bộ nhớ nhỏ hơn so với sử dụng hai bộ từ điển đã gõ mạnh với cấu trúc lớn.

Không cần viết đầy đủ Dictionary<TKey, TValue> triển khai sử dụng hai bộ sưu tập thùng bên trong cho khóa và giá trị và hai danh sách được liên kết cho các chuỗi tắt của nhóm tôi không nghĩ rằng bạn có thể nhận được kết quả tốt hơn nhiều.

+0

Đây là một giải pháp tốt khi TwoWayDictionary được xây dựng trên thời gian chạy, nhưng bây giờ tôi đang suy nghĩ ... Nó thực sự có thể được tuần tự hóa và deserialized, duy trì hiệu suất? –

+0

@Randolph Nó phải là, tất cả những gì bạn cần làm là đặt một thuộc tính '[Serializeable]' và nó sẽ là tốt. Cả hai 'DictionaryBase' và' Hashtable' đã được đánh dấu là serializable. Nhưng bạn sẽ cần phải kiểm tra nó. Nếu bạn không cảm thấy tự do khi đặt một câu hỏi mới về lý do tại sao nó không thành công nếu bạn không thể hiểu được. –

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