是否可以在KeyValuePair<,>
或下一个对象中获取给定Dictionary<,>
的位置,而不是index
或类似?
例如,假设我有以下代码:
Dictionary<Object, String>
dictionary = new Dictionary<Object, String>() {
{ new Object(), "String A" },
{ new Object(), "String B" },
{ new Object(), "String C" },
{ new Object(), "String D" },
{ new Object(), "String E" },
{ new Object(), "String F" },
};
String
knownValue = "String C";
从那里开始,我应该如何获得KeyValuePair<Object, String>
索引或KeyValuePair<Object, String>
"String D"
值?
在给定的示例和我尝试执行此操作的位置,Keys
和Values
都是唯一的。我使用Dictionary<,>
跟踪两个对象,同时知道哪个对象与之关联。
稍微详细一点,我使用此Dictionary<,>
来跟踪Android应用中的位置和Marker
。我被要求在选择Marker
并弹出一张卡并提供有关该位置的基本信息后,启用该卡并显示下一个或上一个位置。
这是此问题进入的地方。我从服务器收到一个位置列表,必须保留该订单。处理完该列表后,我将每个位置与地图上的Marker
相关联。
此时,每当用户点击Marker
时,我都会使用LINQ表达式在Marker
上找到Dictionary<,>
并检索相关位置。
答案 0 :(得分:4)
A Dictionary(TKey,TValue)
,不会以列表格式存储数据,它(非常非常简单地)散列密钥并将其存储在存储桶中,因此它没有&#34; next&#34;的概念。也许你可以考虑使用SortedDictionary(TKey, TValue)。然后,您可以使用迭代器以您需要的顺序遍历元素。
答案 1 :(得分:4)
字典中的顺序是非确定性的
请参阅:The order of elements in Dictionary
你可以使用OrderedDictionary
虽然(https://msdn.microsoft.com/en-us/library/system.collections.specialized.ordereddictionary(v=vs.110).aspx)
答案 2 :(得分:2)
在C#中,Dictionary
没有索引这样的东西 - 对象没有按特定顺序保存。这是因为字典的工作原理,它们根据键的哈希将键和值放在所谓的“桶”中。
如果您需要对要素进行排序,则可以改为使用SortedDictionary
。
也许你只需要枚举所有元素,在这种情况下你应该这样做:
foreach (var kvp in dictionary)
{
if ("String D".Equals(kvp.Value))
; //do stuff
}
如果您需要能够按键以及按值搜索,则可能更适合使用不同的结构。例如,请参阅here
问题编辑后:
编辑让它变得有趣,这应该适合你:
class SortedBiDcit<T1, T2> //this assumes T1 and T2 are different (and not int for indexer) and values are unique
{
Dictionary<T1, Tuple<T2, int>> dict1 = new Dictionary<T1, Tuple<T2, int>>();
Dictionary<T2, T1> dict2 = new Dictionary<T2, T1>();
List<T1> indices = new List<T1>();
public int Count { get { return indices.Count; } }
public T2 this[T1 arg]
{
get { return dict1[arg].Item1; }
}
public T1 this[T2 arg]
{
get { return dict2[arg]; }
}
public Tuple<T1, T2> this[int index]
{
get
{
T1 arg1 = indices[index];
return new Tuple<T1, T2>(arg1, dict1[arg1].Item1);
}
}
public void Add(T1 arg1, T2 arg2)
{
dict1[arg1] = new Tuple<T2, int>(arg2, indices.Count);
dict2[arg2] = arg1;
indices.Add(arg1);
}
public void Remove(T1 arg)
{
var arg2 = dict1[arg];
dict1.Remove(arg);
dict2.Remove(arg2.Item1);
indices.RemoveAt(arg2.Item2);
}
public void Remove(T2 arg)
{
var arg2 = dict2[arg];
var arg1 = dict1[arg2];
dict1.Remove(arg2);
dict2.Remove(arg1.Item1);
indices.RemoveAt(arg1.Item2);
}
}
它缺少基本的错误检查,但您可以从那里获取它。它应该允许你像这样使用它:
var test = new SortedBiDcit<object, string>();
test.Add(new object(), "test");
for (int i = 0; i < test.Count; ++i)
{
var tuple = test[i];
var str = test[tuple.Item1]; //retrieve T2
var obj = test[tuple.Item2]; //retrieve T1
Console.WriteLine(tuple.Item2); //prints "test"
}
希望它有所帮助!
答案 3 :(得分:0)
我认为你应该使用KeyedCollection<TKey,TItem>
,它专为此而设计......
you can do myKeyedCollectionObject[TItem] ---> return TKEY
在示例中,我使用索引或值作为索引。
KeyedCollection<TKey,TItem>
有一个TItems列表(List<TItems>
)和一个Dictionary<TKey,TItem>
两者都在幕后保持同步。
使用它的主要论点是当你想从值中提取键时,因为这就是你想要的......我认为这应该适合你!
答案 4 :(得分:0)
嗯,从技术上讲,这是一种在字典中查找值的索引的方法。
dictionary.Values
字段是Dictionary<T1,T2>.ValueCollection
,其继承自IEnumerable<T2>
。
作为IEnumerable
,您可以使用foreach
进行迭代,或使用类似的内容
IEnumerable<Int32> idxs = dictionary.values.SelectMany(
(string value, Int32 idx) =>
(value == "insertStringHere") ? (new int[]{ idx }) : {new int[]{}}
);
选择您要查找的值的索引(或所有索引,如果有重复)。
我不会推荐它,与其他答案的推理相同,因为Dictionary
不保证值的顺序。它可能适用于SortedDictionary
或SortedList
。
(编辑:或KeyedCollection
明显,https://stackoverflow.com/users/1892381/olivier-albertini指出)
答案 5 :(得分:-1)
由于SortedDictionary
按key
排序,而不是add()
排序,
我相信SortedDictionary
不你想要的是什么。
也许OrderedDictionary
是你想要的,但看起来你是WP的开发人员,OrderedDictionary
是WP的不版本。
您的knownValue
是一个值(不是键),所以我认为最好的方法是:
var list = new List<string>() { .... , "String C", "String D", ... };
// if you still need dict, then:
var dictionary = list.ToDictionary(z => new object());
// whatever, find the "String D"
var knownValue = "String C";
var ret = list.SkipWhile(z => z != knownValue).Skip(1).First();
为什么不创建一个类?
class A
{
Marker;
Location;
}
当用户点击它时,你应该得到A,而不是标记。
答案 6 :(得分:-2)
这个问题实际上有一个相当简单的解决方案 - 尽管不是很好,但它可以完成这项工作。
在这种情况下,我试图从Dictionary
对象获取下一个或上一个条目。不幸的是,它没有类似IndexOf( ... )
的{{1}},所以我无法执行List
之类的操作。
但是Dictionary[index + 1]
个对象可以索引它们。转换为Dictionary
后,通过Dictionary.Keys
或Dictionary.Values
。它不是我们习惯的索引,但它已接近。
考虑到这一点,我可以像这样创建一个扩展名:
List
这些扩展适合我的需要。
有了这个,我可以获得任何给定public static KeyValuePair<K, V> After<K, V>( this Dictionary<K, V> dictionary, K key ) {
Int32 position = dictionary.Keys.ToList().IndexOf( key );
if( position == -1 )
throw new ArgumentException( "No match.", "key" );
position++;
if( position >= dictionary.Count )
position = 0;
K k = dictionary.Keys.ToList()[ position ];
V v = dictionary.Values.ToList()[ position ];
return new KeyValuePair<K, V>( k, v );
}
public static KeyValuePair<K, V> After<K, V>( this Dictionary<K, V> dictionary, V value ) {
Int32 position = dictionary.Values.ToList().IndexOf( value );
if( position == -1 )
throw new ArgumentException( "No match.", "value" );
position++;
if( position >= dictionary.Count )
position = 0;
K k = dictionary.Keys.ToList()[ position ];
V v = dictionary.Values.ToList()[ position ];
return new KeyValuePair<K, V>( k, v );
}
public static KeyValuePair<K, V> Before<K, V>( this Dictionary<K, V> dictionary, K key ) {
Int32 position = dictionary.Keys.ToList().IndexOf( key );
if( position == -1 )
throw new ArgumentException( "No match.", "key" );
position--;
if( position < 0 )
position = dictionary.Count - 1;
K k = dictionary.Keys.ToList()[ position ];
V v = dictionary.Values.ToList()[ position ];
return new KeyValuePair<K, V>( k, v );
}
public static KeyValuePair<K, V> Before<K, V>( this Dictionary<K, V> dictionary, V value ) {
Int32 position = dictionary.Values.ToList().IndexOf( value );
if( position == -1 )
throw new ArgumentException( "No match.", "value" );
position--;
if( position < 0 )
position = dictionary.Count - 1;
K k = dictionary.Keys.ToList()[ position ];
V v = dictionary.Values.ToList()[ position ];
return new KeyValuePair<K, V>( k, v );
}
或After
的条目Before
/ Key
。
您可以查看它有效here。