2012-01-06 32 views
13

Có phương pháp hay kỹ thuật cho phép bạn chèn phần tử vào một số Dictionary<TKey, TValue> đảm bảo rằng mục nằm trong chỉ mục đầu tiên của KeyCollection của từ điển đó.Làm cách nào để chèn phần tử vào chỉ mục đầu tiên trong từ điển?

Ví dụ:

Dictionary<String, String> dic = foo.GetOutput(); 

// `dic` is something like: 

// {"foo", "baa"}, 
// {"a", "b"} 

tôi cần một cái gì đó như:

dic.Add("key", "value", 0); 
// where `0` is the index that `key` to be inserted. 

foreach(KeyValuePair<String, String> key in dic) 
{ 
    Console.WriteLine("{0} = {1}", key.Key, key.Value); 
} 

Output:

key = value 
foo = baa 
a = b 

Bất kỳ sự giúp đỡ rất nhiều đánh giá cao. Cảm ơn trước!

+2

yêu cầu của bạn để làm sử dụng một từ điển là gì? Thứ tự của các mục trong bộ sưu tập từ điển được dự định linh hoạt (bạn có thể sắp xếp lại chúng, v.v.), chỉ mục bị ẩn khỏi sử dụng. Bạn có thể muốn sử dụng một loại bộ sưu tập khác sẽ phù hợp hơn tùy theo nhu cầu của bạn. –

Trả lời

20

Bằng cách không sử dụng từ điển.

Dictionary<TKey, TValue> được triển khai dưới dạng bảng băm.Vị trí của các khóa trong từ điển phụ thuộc vào mã băm, các phương tiện mà mã băm được giảm thêm để cung cấp một chỉ mục vào cấu trúc nội bộ của nó và thứ tự chèn theo cách hoàn toàn phụ thuộc vào cách thực hiện.

Đây không phải là cách duy nhất để triển khai từ điển. SortedDictionary<TKey, TValue> sử dụng cấu trúc cây bên trong và vì vậy luôn giữ các phím theo thứ tự. Trong trường hợp này, chúng tôi vẫn không thể chèn một cái gì đó vào đầu, thay vì chúng tôi chèn một cái gì đó và nó được đưa vào vị trí thích hợp.

Nếu đặt hàng là thứ bạn quan tâm nhất, thì bạn không muốn có một puredictionary cả. Thay vào đó bạn muốn hoặc là List<KeyValuePair<TKey, TValue>> hoặc bạn muốn có cấu trúc cung cấp cả chức năng của danh sách và từ điển, được cung cấp bởi OrderedDictionary. Đây không phải là chung chung, nhưng bạn có thể dễ dàng tạo ra một wrapper chung quanh nó (không cung cấp cho các lợi ích hiệu suất của nội bộ bằng cách sử dụng generics, nhưng không cung cấp cho loại an toàn trong sử dụng).

+0

Vì vậy, mục đích của phương pháp như 'OrderBy' là gì? (LINQ mở rộng). Trong đó thứ tự sẽ liệt kê các mục truy cập? – Keren

+0

@Keren Mục đích là để nhận các phần tử được sắp xếp theo một tiêu chí cụ thể và điều gì đó liệt kê thông qua nó sẽ truy cập các phần tử theo thứ tự đó. (Nguồn sẽ được truy cập theo thứ tự bất kỳ và thứ tự xảy ra khi đã hoàn thành). Tôi không chắc làm thế nào điều này là có liên quan. –

+0

Điều tôi đang cố nói là từ điển không có thứ tự nào không phụ thuộc vào 'Khóa '. Vì lý do này, tôi mong đợi một cách để kiểm soát thứ tự này. Tôi hiểu không có. – Keren

2

Dictionary<TKey, TValue> vốn đã không có thứ tự (hay đúng hơn, thứ tự là không thể đoán trước và không nên dựa vào). Nếu bạn muốn một số loại đặt hàng, bạn cần phải sử dụng một loại khác nhau. Thật khó để đề xuất bất kỳ loại cụ thể nào mà không biết thêm về yêu cầu của bạn.

2

Lớp Dictionary<TKey,TValue> không giữ các mục theo cách được sắp xếp, vì vậy không có mục "đầu tiên".

Có một SortedDictionary<Tkey,TValue> (.NET 4.0+), sắp xếp theo khóa, nhưng một lần nữa, đây là ý tưởng rất mơ hồ về "đầu tiên".

2

Không thể đặt hàng Dictionary<TKey, TValue>.

Bạn có thể thử SortedDictionary<TKey, TValue> thay vào đó, nhưng đó là một trong những lệnh của Key, chứ không phải bằng một chỉ số riêng biệt.

7

Từ điển không có thứ tự; các yếu tố có nghĩa là để được lấy ra với một khóa, có băm trỏ đến vị trí của giá trị của nó.

Những gì bạn có thể muốn là một List <KeyValuePair>, có các yếu tố có thể được chèn vào một chỉ mục cụ thể.

List<KeyValuePair<string, string>> list = dic.ToList(); 
list.Insert(0, new KeyValuePair<string, string>("a", "b")); 

foreach(KeyValuePair<string, string> pair in list) 
    Console.WriteLine("{0} = {1}", pair.Key, pair.Value); 
3

Điều này là không thể với Dictionary<TKey, TValue> vì nó thể hiện giá trị của nó theo kiểu không theo thứ tự khi được liệt kê. Có SortedDictionary<TKey, TValue> cung cấp thứ tự nhưng nó làm như vậy bằng cách sử dụng trực tiếp một giá trị khóa IComparer<TKey>. Tại đây, bạn muốn khóa là String và đặt hàng dựa trên số int. Đó là không thể với một trong các loại.

Tôi nghĩ bạn sẽ cần phải triển khai một loại mới với những ngữ nghĩa rất cụ thể này. Ví dụ.

class OrderedMap<TKey, TValue> { 
    private readonly Dictionary<TKey, TValue> _map = new Dictionary<TKey, TValue>(); 
    private readonly List<TKey> _list = new List<TKey>(); 

    public void Add(TKey key, TValue value) { 
    if (!_map.ContainsKey(key)) { 
     _list.Add(key); 
    } 
    _map[key] = value; 
    } 

    public void Add(TKey key, TValue value, int index) { 
    if (_map.ContainsKey(key)) { 
     _list.Remove(key); 
    } 
    _map[key] = value; 
    _list.Insert(index, key); 
    } 

    public TValue GetValue(TKey key) { 
    return _map[key]; 
    } 

    public IEnumerabe<KeyValuePair<TKey, TValue>> GetItems() { 
    foreach (var key in _list) { 
     var value = _map[key]; 
     yield return new KeyValuePair<TKey, TValue>(key, value); 
    } 
    } 
} 

Lưu ý điều này đi kèm với một số khác biệt hiệu suất không tầm thường so với số Dictionary<TKey, TValue> truyền thống. Ví dụ: AddRemove chậm hơn.

1

đây là giải pháp của tôi, có thể không phải là giải pháp tốt nhất nhưng nó hoạt động. =)

public static ComboBox FillDropDownList(Dictionary<String, String> dictionary, ComboBox dropDown, String selecione) 
{ 
    var d = new SortedDictionary<String, String>(); 

    d.Add("0", selecione); 

    foreach (KeyValuePair<string, string> pair in dictionary) 
    { 
     d.Add(pair.Key, pair.Value); 
    } 

    dropDown.DataSource = new BindingSource(d, null); 
    dropDown.DisplayMember = "Value"; 
    dropDown.ValueMember = "Key"; 

    dropDown.SelectedIndex = 0; 

    return dropDown; 
} 
3

Tôi biết đó là câu hỏi ba năm. Nhưng tìm thấy giải pháp cho vấn đề này. Nó có thể giúp một người nào đó

Dictionary<String, String> dic = foo.GetOutput(); 

dic = (new Dictionary<string, string> {{"key","value"}}).Concat(dic).ToDictionary(k => k.Key, v => v.Value); 

này sẽ chèn phần tử vào đầu từ điển :)

+1

Đây là một chi tiết thực hiện, cũng nếu từ điển thay đổi kích cỡ mảng nội bộ của nó, bạn không được đảm bảo rằng mục đầu tiên sẽ ở lại mục đầu tiên. –

+0

@MJK Cảm ơn .. điều này đã giúp .. – Arnab

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