I'm menggunakan Kamus<string, int>
mana int
adalah hitungan kunci.
Sekarang, saya perlu untuk mengakses terakhir dimasukkan Kunci dalam Kamus, tapi saya tidak tahu nama itu. Yang jelas upaya:
int LastCount = mydict[mydict.keys[mydict.keys.Count]];
tidak bekerja, karena Kamus.Tombol
tidak menerapkan []-pengindeks.
Aku hanya bertanya-tanya jika ada kelas yang sama? Saya berpikir tentang menggunakan Stack, tapi itu hanya menyimpan string. Sekarang saya dapat membuat saya sendiri struct dan kemudian menggunakan Stack<MyStruct>
, tapi aku bertanya-tanya jika ada alternatif lain, pada dasarnya sebuah Kamus yang mengimplementasikan sebuah []-indexer pada Tombol?
Seperti @Falanwe poin di komentar, melakukan sesuatu seperti ini adalah salah:
int LastCount = mydict.Keys.ElementAt(mydict.Count -1);
Anda tidak tergantung pada urutan kunci dalam Kamus. Jika anda perlu memesan, anda harus menggunakan OrderedDictionary, seperti yang disarankan dalam hal ini jawaban. Lain jawaban pada halaman ini menarik juga.
Anda dapat menggunakan OrderedDictionary.
Merupakan kumpulan kunci/nilai pasangan yang dapat diakses dengan kunci atau indeks.
Kamus adalah sebuah Tabel Hash, sehingga anda tidak memiliki ide urutan penyisipan!
Jika anda ingin tahu terakhir dimasukkan kunci saya akan menyarankan memperpanjang Kamus mencakup LastKeyInserted nilai.
E. g.:
public MyDictionary<K, T> : IDictionary<K, T>
{
private IDictionary<K, T> _InnerDictionary;
public K LastInsertedKey { get; set; }
public MyDictionary()
{
_InnerDictionary = new Dictionary<K, T>();
}
#region Implementation of IDictionary
public void Add(KeyValuePair<K, T> item)
{
_InnerDictionary.Add(item);
LastInsertedKey = item.Key;
}
public void Add(K key, T value)
{
_InnerDictionary.Add(key, value);
LastInsertedKey = key;
}
.... rest of IDictionary methods
#endregion
}
Anda akan mengalami masalah namun bila anda menggunakan .Hapus()
sehingga untuk mengatasi hal ini anda akan memiliki untuk menjaga daftar memerintahkan kunci yang dimasukkan.
Mengapa don't anda hanya memperpanjang kamus kelas untuk menambahkan tombol terakhir dimasukkan properti. Sesuatu seperti berikut mungkin?
public class ExtendedDictionary : Dictionary<string, int>
{
private int lastKeyInserted = -1;
public int LastKeyInserted
{
get { return lastKeyInserted; }
set { lastKeyInserted = value; }
}
public void AddNew(string s, int i)
{
lastKeyInserted = i;
base.Add(s, i);
}
}
Anda selalu bisa melakukan ini:
string[] temp = new string[mydict.count];
mydict.Keys.CopyTo(temp, 0)
int LastCount = mydict[temp[mydict.count - 1]]
Tapi saya tidak't merekomendasikan hal ini. Ada's tidak ada jaminan bahwa yang terakhir dimasukkan kunci akan berada di akhir dari array. Pemesanan untuk Tombol di MSDN tidak ditentukan, dan dapat berubah. Saya sangat singkat tes, tampaknya berada di urutan penyisipan, tapi anda'a menjadi lebih baik dari bangunan yang tepat pembukuan seperti tumpukan--seperti yang anda sarankan (meskipun aku don't melihat kebutuhan dari struct berdasarkan pernyataan lain)--atau variabel tunggal cache jika anda hanya perlu tahu kunci terbaru.
Saya pikir anda dapat melakukan sesuatu seperti ini, sintaks mungkin salah, belum digunakan C# sementara Untuk mendapatkan item terakhir
Dictionary<string, int>.KeyCollection keys = mydict.keys;
string lastKey = keys.Last();
atau gunakan Max bukan Terakhir untuk mendapatkan nilai max, saya tidak tahu mana yang sesuai dengan kode yang lebih baik.
Salah satu alternatif yang akan menjadi KeyedCollection jika kunci tertanam dalam nilai.
Hanya membuat dasar penerapan dalam sebuah disegel kelas untuk digunakan.
Jadi untuk menggantikan Kamus<string, int>
(yang isn't contoh yang sangat baik karena ada isn't yang jelas kunci untuk int).
private sealed class IntDictionary : KeyedCollection<string, int>
{
protected override string GetKeyForItem(int item)
{
// The example works better when the value contains the key. It falls down a bit for a dictionary of ints.
return item.ToString();
}
}
KeyedCollection<string, int> intCollection = new ClassThatContainsSealedImplementation.IntDictionary();
intCollection.Add(7);
int valueByIndex = intCollection[0];
Saya setuju dengan bagian kedua dari Patrick's jawaban. Bahkan jika dalam beberapa tes yang tampaknya untuk menjaga penyisipan order, dokumentasi (dan perilaku normal untuk kamus dan hash) secara eksplisit menyatakan pemesanan yang tidak ditentukan.
Anda're hanya meminta masalah tergantung pada urutan tombol. Tambahkan anda sendiri pembukuan (seperti Patrick mengatakan, hanya satu variabel untuk terakhir menambahkan key) untuk memastikan. Juga, don't tergoda oleh semua metode seperti Terakhir dan Max pada kamus sebagai orang-orang yang mungkin dalam kaitannya dengan kunci pembanding (I'm tidak yakin tentang hal itu).
Dalam kasus anda memutuskan untuk menggunakan kode berbahaya yang tunduk pada kerusakan, ekstensi ini fungsi akan mengambil kunci dari sebuah Kamus<K,V>
menurut internal pengindeksan (yang untuk Mono dan .NET saat ini tampaknya berada dalam urutan yang sama seperti yang anda dapatkan dengan menyebutkan Kunci
properti).
Hal ini jauh lebih baik untuk menggunakan Linq: dict.Kunci-kunci.ElementAt(i)
, tapi fungsi itu akan iterate O(N); berikut ini adalah O(1) tapi dengan refleksi kinerja penalti.
using System;
using System.Collections.Generic;
using System.Reflection;
public static class Extensions
{
public static TKey KeyByIndex<TKey,TValue>(this Dictionary<TKey, TValue> dict, int idx)
{
Type type = typeof(Dictionary<TKey, TValue>);
FieldInfo info = type.GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance);
if (info != null)
{
// .NET
Object element = ((Array)info.GetValue(dict)).GetValue(idx);
return (TKey)element.GetType().GetField("key", BindingFlags.Public | BindingFlags.Instance).GetValue(element);
}
// Mono:
info = type.GetField("keySlots", BindingFlags.NonPublic | BindingFlags.Instance);
return (TKey)((Array)info.GetValue(dict)).GetValue(idx);
}
};
Cara anda bernada pertanyaan yang membuat saya percaya bahwa int dalam Kamus berisi item's "posisi" di Kamus. Dilihat dari pernyataan bahwa kunci aren't disimpan dalam urutan bahwa mereka're menambahkan, jika ini benar, itu berarti kunci.Menghitung (atau .Count - 1, jika anda're zero-based) harus tetap selalu menjadi yang nomor terakhir-tombol masuk?
Jika itu's benar, apakah ada alasan yang dapat anda't bukan menggunakan Kamus<int, string> sehingga anda dapat menggunakan mydict[ mydict.Kunci-kunci.Count ]?
Saya don't tahu apakah ini akan bekerja karena saya'm cukup yakin bahwa kunci aren't disimpan dalam urutan yang mereka ditambahkan, tapi anda bisa melemparkan KeysCollection untuk Daftar
Satu-satunya hal yang dapat saya pikirkan adalah untuk menyimpan kunci dalam pencarian daftar dan menambahkan kunci ke dalam daftar sebelum anda menambahkannya ke dalam kamus... itu's tidak cukup tho.
Untuk memperluas Daniels posting dan komentar mengenai kunci, karena kunci tertanam dalam nilai pokoknya, anda bisa resor untuk menggunakan KeyValuePair<TKey, TValue>
sebagai nilai. Utama alasan untuk ini adalah bahwa, secara umum, Kunci isn't tentu langsung derivable dari nilai.
Maka itu'd terlihat seperti ini:
public sealed class CustomDictionary<TKey, TValue>
: KeyedCollection<TKey, KeyValuePair<TKey, TValue>>
{
protected override TKey GetKeyForItem(KeyValuePair<TKey, TValue> item)
{
return item.Key;
}
}
Untuk menggunakan ini, seperti dalam contoh sebelumnya, anda'd lakukan:
CustomDictionary<string, int> custDict = new CustomDictionary<string, int>();
custDict.Add(new KeyValuePair<string, int>("key", 7));
int valueByIndex = custDict[0].Value;
int valueByKey = custDict["key"].Value;
string keyByIndex = custDict[0].Key;
Anda juga dapat menggunakan SortedList dan Generik rekan. Dua kelas dan Andrew Peters jawaban disebutkan OrderedDictionary adalah kamus kelas di mana barang-barang dapat diakses dengan index (posisi) serta oleh kunci. Cara menggunakan kelas-kelas ini anda dapat menemukan: SortedList Kelas , SortedList Kelas Generik .
Visual Studio's UserVoice memberikan link ke generic OrderedDictionary implementation oleh dotmore.
Tapi jika anda hanya perlu untuk mendapatkan pasangan kunci/nilai dengan indeks dan don't perlu untuk mendapatkan nilai-nilai kunci, anda dapat menggunakan salah satu trik sederhana. Menyatakan beberapa kelas generik (saya menyebutnya ListArray) sebagai berikut:
class ListArray<T> : List<T[]> { }
Anda juga dapat menyatakan dengan konstruktor:
class ListArray<T> : List<T[]>
{
public ListArray() : base() { }
public ListArray(int capacity) : base(capacity) { }
}
Misalnya, anda membaca beberapa pasangan kunci/nilai dari sebuah file dan hanya ingin menyimpan mereka dalam urutan yang mereka baca sehingga untuk mendapatkan mereka kemudian oleh indeks:
ListArray<string> settingsRead = new ListArray<string>();
using (var sr = new StreamReader(myFile))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] keyValueStrings = line.Split(separator);
for (int i = 0; i < keyValueStrings.Length; i++)
keyValueStrings[i] = keyValueStrings[i].Trim();
settingsRead.Add(keyValueStrings);
}
}
// Later you get your key/value strings simply by index
string[] myKeyValueStrings = settingsRead[index];
Seperti anda mungkin telah menyadari, anda dapat belum tentu hanya pasangan kunci/nilai dalam ListArray. Item array dapat dari setiap panjang, seperti di jagged array.