77

I have a Dictionary<string, string>.

I need to look within that dictionary to see if a value exists based on input from somewhere else and if it exists remove it.

ContainsValue just says true/false and not the index or key of that item.

Help!

Thanks

EDIT: Just found this - what do you think?

var key = (from k in dic where string.Compare(k.Value, "two", true) ==
0 select k.Key).FirstOrDefault();

EDIT 2: I also just knocked this up which might work

foreach (KeyValuePair<string, string> kvp in myDic)
{
    if (myList.Any(x => x.Id == kvp.Value))
        myDic.Remove(kvp.Key);
}
4
  • I think you need a BiDictionary. Check this question: stackoverflow.com/questions/255341/… Commented Oct 28, 2009 at 12:22
  • 6
    @Edit 2: you're going to remove things from a collection while enumerating it? Doesn't that throw an exception? Commented Oct 28, 2009 at 12:40
  • @JustLoren - Good Point! Will enumerate the list and run the LINQ to find the key if it exists and then just call remove from my dictionary without concern Commented Oct 28, 2009 at 12:46
  • 1
    @Jon, the foreach is fine as well, as long as you add a break after you've found and removed your key. Commented Oct 28, 2009 at 14:01

6 Answers 6

158

Are you trying to remove a single value or all matching values?

If you are trying to remove a single value, how do you define the value you wish to remove?

The reason you don't get a key back when querying on values is because the dictionary could contain multiple keys paired with the specified value.

If you wish to remove all matching instances of the same value, you can do this:

foreach(var item in dic.Where(kvp => kvp.Value == value).ToList())
{
    dic.Remove(item.Key);
}

And if you wish to remove the first matching instance, you can query to find the first item and just remove that:

var item = dic.First(kvp => kvp.Value == value);

dic.Remove(item.Key);

Note: The ToList() call is necessary to copy the values to a new collection. If the call is not made, the loop will be modifying the collection it is iterating over, causing an exception to be thrown on the next attempt to iterate after the first value is removed.

Sign up to request clarification or add additional context in comments.

4 Comments

First code example doesn't work, because its not allowed to modify collection in foreach loop.
An anonymous edit removed some of the necessary code. I'll put some of it back.
In the second case, you'll get better performance by using this query: foreach(var item in dic.Where(kvp => kvp.Value == value).Take(1).ToList()) and this also makes the break unnecessary.
That ToList trick is clever...it would have saved me from almost every for loop I've ever written.
11
Dictionary<string, string> source
//
//functional programming - do not modify state - only create new state
Dictionary<string, string> result = source
  .Where(kvp => string.Compare(kvp.Value, "two", true) != 0)
  .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
//
// or you could modify state
List<string> keys = source
  .Where(kvp => string.Compare(kvp.Value, "two", true) == 0)
  .Select(kvp => kvp.Key)
  .ToList();

foreach(string theKey in keys)
{
  source.Remove(theKey);
}

Comments

1

Loop through the dictionary to find the index and then remove it.

1 Comment

As noted in the accepted answer, if you remove a dictionary item while looping through the dictionary it will throw an error if there are values left in the dictionary after the one you removed.
1

Here is a method you can use:

    public static void RemoveAllByValue<K, V>(this Dictionary<K, V> dictionary, V value)
    {
        foreach (var key in dictionary.Where(
                kvp => EqualityComparer<V>.Default.Equals(kvp.Value, value)).
                Select(x => x.Key).ToArray())
            dictionary.Remove(key);
    }

Comments

0

You can use the following as extension method

 public static void RemoveByValue<T,T1>(this Dictionary<T,T1> src , T1 Value)
    {
        foreach (var item in src.Where(kvp => kvp.Value.Equals( Value)).ToList())
        {
            src.Remove(item.Key);
        }
    }

1 Comment

This is the same as the first code snippet in the accepted answer.
-1

In my case I use this

  var key=dict.FirstOrDefault(m => m.Value == s).Key;
            dict.Remove(key);

1 Comment

This is the same as the second code snippet in the accepted answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.