C #에서 값으로 사전 키를 어떻게 얻습니까?
Dictionary<string, string> types = new Dictionary<string, string>()
{
{"1", "one"},
{"2", "two"},
{"3", "three"}
};
나는 이런 것을 원한다.
getByValueKey(string value);
getByValueKey("one")
반환해야합니다 "1"
.
가장 좋은 방법은 무엇입니까? 아마도 HashTable, SortedLists입니까?
답변
값이 반드시 고유하지 않아도되므로 조회를 수행해야합니다. 다음과 같이 할 수 있습니다 :
var myKey = types.FirstOrDefault(x => x.Value == "one").Key;
값이 고유하고 읽기보다 덜 자주 삽입되는 경우 값이 키이고 키가 값인 역 사전을 작성하십시오.
답변
당신은 그렇게 할 수 있습니다 :
KeyValuePair<TKey, TValue>
사전의 모든를 반복 하여 (사전에 많은 항목이있는 경우 상당한 성능 저하)- 하나의 값 대 키 맵핑과 하나의 키 대 값 맵핑 (메모리에서 두 배의 공간을 차지함)에 대해 두 개의 사전을 사용하십시오.
성능을 고려하지 않으면 방법 1을 사용하고 메모리를 고려하지 않으면 방법 2를 사용하십시오.
또한 모든 키는 고유해야하지만 값이 고유하지 않아도됩니다. 지정된 값을 가진 둘 이상의 키가있을 수 있습니다.
키-값 관계를 되돌릴 수없는 이유가 있습니까?
답변
Linq 바인딩을 사용할 수없고 람다를 명시 적으로 확장해야하는 상황에있었습니다. 다음과 같은 간단한 기능을 수행했습니다.
public static T KeyByValue<T, W>(this Dictionary<T, W> dict, W val)
{
T key = default;
foreach (KeyValuePair<T, W> pair in dict)
{
if (EqualityComparer<W>.Default.Equals(pair.Value, val))
{
key = pair.Key;
break;
}
}
return key;
}
다음과 같이 호출하십시오.
public static void Main()
{
Dictionary<string, string> dict = new Dictionary<string, string>()
{
{"1", "one"},
{"2", "two"},
{"3", "three"}
};
string key = KeyByValue(dict, "two");
Console.WriteLine("Key: " + key);
}
.NET 2.0 및 기타 제한된 환경에서 작동합니다.
답변
아마도 이런 식으로 :
foreach (var keyvaluepair in dict)
{
if(Object.ReferenceEquals(keyvaluepair.Value, searchedObject))
{
//dict.Remove(keyvaluepair.Key);
break;
}
}
답변
이중 조회 클래스를 만들었습니다.
/// <summary>
/// dictionary with double key lookup
/// </summary>
/// <typeparam name="T1">primary key</typeparam>
/// <typeparam name="T2">secondary key</typeparam>
/// <typeparam name="TValue">value type</typeparam>
public class cDoubleKeyDictionary<T1, T2, TValue> {
private struct Key2ValuePair {
internal T2 key2;
internal TValue value;
}
private Dictionary<T1, Key2ValuePair> d1 = new Dictionary<T1, Key2ValuePair>();
private Dictionary<T2, T1> d2 = new Dictionary<T2, T1>();
/// <summary>
/// add item
/// not exacly like add, mote like Dictionary[] = overwriting existing values
/// </summary>
/// <param name="key1"></param>
/// <param name="key2"></param>
public void Add(T1 key1, T2 key2, TValue value) {
lock (d1) {
d1[key1] = new Key2ValuePair {
key2 = key2,
value = value,
};
d2[key2] = key1;
}
}
/// <summary>
/// get key2 by key1
/// </summary>
/// <param name="key1"></param>
/// <param name="key2"></param>
/// <returns></returns>
public bool TryGetValue(T1 key1, out TValue value) {
if (d1.TryGetValue(key1, out Key2ValuePair kvp)) {
value = kvp.value;
return true;
} else {
value = default;
return false;
}
}
/// <summary>
/// get key1 by key2
/// </summary>
/// <param name="key2"></param>
/// <param name="key1"></param>
/// <remarks>
/// 2x O(1) operation
/// </remarks>
/// <returns></returns>
public bool TryGetValue2(T2 key2, out TValue value) {
if (d2.TryGetValue(key2, out T1 key1)) {
return TryGetValue(key1, out value);
} else {
value = default;
return false;
}
}
/// <summary>
/// get key1 by key2
/// </summary>
/// <param name="key2"></param>
/// <param name="key1"></param>
/// <remarks>
/// 2x O(1) operation
/// </remarks>
/// <returns></returns>
public bool TryGetKey1(T2 key2, out T1 key1) {
return d2.TryGetValue(key2, out key1);
}
/// <summary>
/// get key1 by key2
/// </summary>
/// <param name="key2"></param>
/// <param name="key1"></param>
/// <remarks>
/// 2x O(1) operation
/// </remarks>
/// <returns></returns>
public bool TryGetKey2(T1 key1, out T2 key2) {
if (d1.TryGetValue(key1, out Key2ValuePair kvp1)) {
key2 = kvp1.key2;
return true;
} else {
key2 = default;
return false;
}
}
/// <summary>
/// remove item by key 1
/// </summary>
/// <param name="key1"></param>
public void Remove(T1 key1) {
lock (d1) {
if (d1.TryGetValue(key1, out Key2ValuePair kvp)) {
d1.Remove(key1);
d2.Remove(kvp.key2);
}
}
}
/// <summary>
/// remove item by key 2
/// </summary>
/// <param name="key2"></param>
public void Remove2(T2 key2) {
lock (d1) {
if (d2.TryGetValue(key2, out T1 key1)) {
d1.Remove(key1);
d2.Remove(key2);
}
}
}
/// <summary>
/// clear all items
/// </summary>
public void Clear() {
lock (d1) {
d1.Clear();
d2.Clear();
}
}
/// <summary>
/// enumerator on key1, so we can replace Dictionary by cDoubleKeyDictionary
/// </summary>
/// <param name="key1"></param>
/// <returns></returns>
public TValue this[T1 key1] {
get => d1[key1].value;
}
/// <summary>
/// enumerator on key1, so we can replace Dictionary by cDoubleKeyDictionary
/// </summary>
/// <param name="key1"></param>
/// <returns></returns>
public TValue this[T1 key1, T2 key2] {
set {
lock (d1) {
d1[key1] = new Key2ValuePair {
key2 = key2,
value = value,
};
d2[key2] = key1;
}
}
}
답변
types.Values.ToList().IndexOf("one");
Values.ToList ()는 사전 값을 객체 목록으로 변환합니다. IndexOf ( “one”)은 “one”을 찾기 위해 새 List를 검색하고 사전의 키 / 값 쌍의 색인과 일치하는 색인을 반환합니다.
이 방법은 사전 키를 신경 쓰지 않고 찾고자하는 값의 인덱스를 반환합니다.
사전에 하나 이상의 “하나”값이있을 수 있습니다. 이것이 바로 “get key”방법이없는 이유입니다.
답변
아래 코드는 고유 값 데이터를 포함하는 경우에만 작동합니다
public string getKey(string Value)
{
if (dictionary.ContainsValue(Value))
{
var ListValueData=new List<string>();
var ListKeyData = new List<string>();
var Values = dictionary.Values;
var Keys = dictionary.Keys;
foreach (var item in Values)
{
ListValueData.Add(item);
}
var ValueIndex = ListValueData.IndexOf(Value);
foreach (var item in Keys)
{
ListKeyData.Add(item);
}
return ListKeyData[ValueIndex];
}
return string.Empty;
}