按值获取字典键

时间:2010-03-14 22:23:35

标签: c# dictionary

如何在C#中按值获取Dictionary键?

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

我想要这样的事情:

getByValueKey(string value);

getByValueKey("one")必须返回"1"

这样做的最佳方式是什么?也许是HashTable,SortedLists?

9 个答案:

答案 0 :(得分:560)

值不一定必须是唯一的,因此您必须进行查找。你可以这样做:

var myKey = types.FirstOrDefault(x => x.Value == "one").Key;

如果值是唯一的并且插入频率低于读取值,则创建一个逆字典,其中值是键,键是值。

答案 1 :(得分:24)

你可以这样做:

  1. 循环遍历字典中的所有KeyValuePair<TKey, TValue>(如果字典中有多个条目,这将是一个相当大的性能点击)
  2. 使用两个词典,一个用于值到键映射,另一个用于键到值映射(这将占用内存空间的两倍)。
  3. 如果不考虑性能,请使用方法1,如果不考虑内存,请使用方法2。

    此外,所有键必须是唯一的,但这些值不必是唯一的。您可能有多个具有指定值的键。

    你有什么理由不能扭转键值关系吗?

答案 2 :(得分:2)

我遇到Linq绑定不可用并且必须明确扩展lambda的情况。它产生了一个简单的功能:

public static string KeyByValue(Dictionary<string, string> dict, string val)
{
    string key = null;
    foreach (KeyValuePair<string, string> pair in dict)
    {
        if (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和其他有限的环境。

答案 3 :(得分:1)

public static string GetKeyFromValue(string valueVar)
{
   foreach (string keyVar in dictionaryVar.Keys) 
   { 
      if (dictionaryVar[keyVar] == valueVar)
      {
         return keyVar;
      }
   }
   return null;
}

其他人可能有更有效的答案,但我觉得这对我个人来说更直观,而且在我的情况下有效,所以我会分享它,以防其他人同意

答案 4 :(得分:-1)

可能是这样的:

foreach (var keyvaluepair in dict)
{
    if(Object.ReferenceEquals(keyvaluepair.Value, searchedObject))
    {
        //dict.Remove(keyvaluepair.Key);
        break;
    }
}

答案 5 :(得分:-1)

我创建了一个双重查询类:

/// <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;
            }
        }
    }

答案 6 :(得分:-2)

以下代码仅在包含唯一值数据时才有效

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;
}

答案 7 :(得分:-3)

types.Values.ToList().IndexOf("one");

Values.ToList()将字典值转换为对象列表。 IndexOf(“one”)搜索新列表,查找“one”并返回与字典中键/值对的索引匹配的索引。

此方法不关心字典键,只返回您要查找的值的索引。

请记住,字典中可能有多个“one”值。这就是没有“获取关键”方法的原因。

答案 8 :(得分:-10)

我有非常简单的方法来做到这一点。它对我来说非常完美。

Dictionary<string, string> types = new Dictionary<string, string>();

types.Add("1", "one");
types.Add("2", "two");
types.Add("3", "three");

Console.WriteLine("Please type a key to show its value: ");
string rLine = Console.ReadLine();

if(types.ContainsKey(rLine))
{
    string value_For_Key = types[rLine];
    Console.WriteLine("Value for " + rLine + " is" + value_For_Key);
}