How to check if a MultiValueDictionary contains a specific value - c#

MultiValueDictionary is an experimental implementation of a multi-value dictionary in c#. It allows you to have multiple values per key. I need help creating code that works like,
(If MultiValueDictionary contains value "pudding", then do this). Here is a code example of what I need:
Class field declaration:
public MultiValueDictionary<string, string> _cookBook = new MultiValueDictionary<string, string>();
Then using in some method:
_cookBook.Add("food", "icing");
_cookBook.Add("food", "pudding");
_cookBook.Add("dessert", "pudding");
if(_cookBook.Contains("pudding"))
{
//Do this
}
MultiValueDictionary is available through NuGet as Microsoft.Experimental.Collections. Since this is a relatively new type of dictionary, I'm not finding a lot of information on it. Any help on how to accomplish this would be greatly appreciated.

I think you can do that as usual:
//If you know item key and value
if (_cookBook.Contains("food", "icing"))
{
//Do something
}
//If you know item key
if (_cookBook.ContainsKey("food"))
{
//Do something
}
//If you know item value
if (_cookBook.ContainsValue("icing"))
{
//Do something
}
Tested with Microsoft Experimental Collections 1.0.3-alpha

Related

How to avoid duplicate value in list Using C# in unity

I am newbie in unity and use C#, actually i am python developer i try to make a list which can holds only unique Values and if some duplicate value come it will not allow to enter in list
List<int> iList = new List<int>();
iList.Add(2);
iList.Add(3);
iList.Add(5);
iList.Add(7);
list =[2,3,5,7]
**in python we just do this to avoid duplicate in list **
if(iList.indexof(value)!=-1){
iList.append(value)
}
But what should we do in C# to achieve very similar results Thanks
Your effort will be highly appreciated
C# List has similar method:
if (!iList.Contains(value)) iList.Add(value);
Alternatively you can use a HashSet<int>. There you don't need to add any conditions:
var hasSet = new HashSet<int>();
hashSet.Add(1);
hashSet.Add(1);
In C# we (can) just do this to avoid duplicate in list:
if (iList.IndexOf(value) == -1 ) {
iList.Add(value);
}
A HashSet would ensure you only have one instance of any object. Or a Dictionary if you want to have a key that is different to the object itself. Again dictionaries do not allow duplicate keys.
A HashSet will not throw an exception if you try to put in a duplicate it just won't add it.
A dictionary will throw a duplicate key exception.
Consider to build your own type of List that will never add duplicates
public class NoDuplicatesList<T> : List<T>
{
public override Add(T Item)
{
if (!Contains(item))
base.Add(item);
}
}

Searching a String in a Dictionary

I have this Class Form1.cs where I created my GUI, It also has a combobox with following functionality:
string SelectedItemName = (string)comboBox2.SelectedItem.ToString();
Console.WriteLine(SelectedItemName);
if (comboBox2.SelectedIndex > -1)
{
testvariabel2.GetSessionName();
}
So I check if the user has chose something from the ComboBox and than I call the Function GetSessionName in my other Class CTestRack.cs.
Dictionary<string, Dictionary<string, string>> newDictionary = new Dictionary<string,Dictionary<string, string>>();
foreach (SectionData section in data.Sections)
{
var keyDictionary = new Dictionary<string, string>();
foreach (KeyData key in section.Keys)
keyDictionary.Add(key.KeyName.ToString(), key.Value.ToString());
newDictionary.Add(section.SectionName.ToString(), keyDictionary);
if (newDictionary.ContainsKey(testvariabel.SelectedItemName))
{
Console.WriteLine("Key: {0}, Value: {1}", keyDictionary[testvariabel.SelectedItemName]);
}
else Console.WriteLine("Couldn't check Selected Name");
}
Here I'd like to check if the String SelectedItemName exists in my Dictionary, but I always get the Systen.ArgumentNullException that the String SelectedItemName is NULL in my CTestRackClass.
Now my question, how do I search the dictionary in CTestRack for the String setted in the other Class
Form1 ?
Well... actually you got the looking into the dictionary right ! To find out if a key is present in a dictionary, you use ContainsKey.
if(myDictionary.ContainsKey(myKey))
{
//do something
}
However, your problems comes from the fact that null is never a valid key in a dictionary (mainly because null doesn't have a proper hash code). So you need to ensure that the key you're looking for is not null. From your code, I guess that testvariabel.SelectedItemName has not been set as it should.
Moreover there is a more efficient way to look if a value is present before doing something with it. Use TryGetValue:
TValue val;
if(myDictionary.TryGetValue(myKey, out val))
{
//do something with val
}
That way you don't need to access myDictionary[myKey]. If you use ContainsKey, you are in fact accessing the same value twice. That a small cost in most cases, but very easy to avoid, so you should give it a try.
Note that I answered only the specific question about looking into a dictionary. I cannot say anything about the correctness of your code as a whole.
I see there are two clear issues with your code.
You are checking if a key exists in one dictionary (newDictionary) but trying to retrieve it from another (keyDictionary )
You are try to look up keys in the dictionary even before it's completely built. Move the if check outside of foreach loop.

C# Copy one record from one dictionary to another

I need to copy one record from one dictionary to another, only one. I have tried the below, It doesn't copy one but everything due to that its in the loop. And I need to check if the key is not already copied over to the second dictionary that's why I looped over the first dictionary.
foreach (int key in firstDict.Keys)
{
if (!secondDict.ContainsKey(key))
secondDict.Add(key, firstDict[key]);
else {break;}
}
Please help, should you require more info please let me know.
Try this:
foreach (int key in firstDict.Keys)
{
if (!secondDict.ContainsKey(key))
{
secondDict.Add(key, firstDict[key]);
break;
}
}
A tiny bit more efficient than the others answers already posted (saves one dictionary lookup).
foreach(var kvp in firstDict)
{
if(!secondDict.ContainsKey(kvp.Key))
{
secondDict[kvp.Key] = kvp.Value;
break;
}
}
And if you're familiar with linq you may want to avoid the whole foreach ... break pattern. That pattern is pretty ugly and more importantly confusing: it looks like you want to copy everything when you really want to copy just one. Your question itself is proof of how confusing it is: if you don't get a pattern that should be simple right, that probably means the pattern is not very good. The following will do the work, and it's crystal clear it will only add ONE (at most) entry to the second dictionary.
var missingEntry = firstDict
// cast beacause KeyValuePair is a struct and I want to detect the case where there is no missing entry
.Cast<KeyValuePair<TKey,TValue>?>()
.FirstOrDefault(kvp => !secondDict.ContainsKey(kvp.Key));
// check whether there truely is a missing entry.
if (missingEntry != null)
{
secondDict[missingEntry.Key] = missingEntry.Value;
}
remove the else clause
foreach (int key in firstDict.Keys)
{
if (!secondDict.ContainsKey(key)) {
secondDict.Add(key, firstDict[key]);
break;
}
}
I suppose you have the key of that row in a certain variable that i will call key. here for example I'll set its value to 3.
int key = 3;
if (!secondDict.ContainsKey(key))
secondDict.Add(key, firstDict[key]);
EDIT:
If you want only any single entry that is not present in present in secondDict:
foreach (KeyValuePair<int, MyValueType> kvp in firstDict) //Replace MyValueType with the real value type in firstDict
{
if (!secondDict.ContainsKey(kvp.Key))
{
secondDict.Add(kvp.Key, kvp.Value);
break;
}
}

Change cardinality of item in C# dictionary

I've got a dictionary, something like
Dictionary<Foo,String> fooDict
I step through everything in the dictionary, e.g.
foreach (Foo foo in fooDict.Keys)
MessageBox.show(fooDict[foo]);
It does that in the order the foos were added to the dictionary, so the first item added is the first foo returned.
How can I change the cardinality so that, for example, the third foo added will be the second foo returned? In other words, I want to change its "index."
If you read the documentation on MSDN you'll see this:
"The order in which the items are returned is undefined."
You can't gaurantee the order, because a Dictionary is not a list or an array. It's meant to look up a value by the key, and any ability to iterate values is just a convenience but the order is not behavior you should depend on.
You may be interested in the OrderedDicationary class that comes in System.Collections.Specialized namespace.
If you look at the comments at the very bottom, someone from MSFT has posted this interesting note:
This type is actually misnamed; it is not an 'ordered' dictionary as such, but rather an 'indexed' dictionary. Although, today there is no equivalent generic version of this type, if we add one in the future it is likely that we will name such as type 'IndexedDictionary'.
I think it would be trivial to derive from this class and make a generic version of OrderedDictionary.
I am not fully educated in the domain to properly answer the question, but I have a feeling that the dictionary sorts the values according to the key, in order to perform quick key search. This would suggest that the dictionary is sorted by key values according to key comparison. However, looking at object methods, I assume they are using hash codes to compare different objects considering there is no requirement on the type used for keys. This is only a guess. Someone more knowledgey should fill in with more detail.
Why are you interested in manipulating the "index" of a dictionary when its purpose is to index with arbitrary types?
I don't know if anyone will find this useful, but here's what I ended up figuring out. It seems to work (by which I mean it doesn't throw any exceptions), but I'm still a ways away from being able to test that it works as I hope it does. I have done a similar thing before, though.
public void sortSections()
{
//OMG THIS IS UGLY!!!
KeyValuePair<ListViewItem, TextSection>[] sortable = textSecs.ToArray();
IOrderedEnumerable<KeyValuePair<ListViewItem, TextSection>> sorted = sortable.OrderBy(kvp => kvp.Value.cardinality);
foreach (KeyValuePair<ListViewItem, TextSection> kvp in sorted)
{
TextSection sec = kvp.Value;
ListViewItem key = kvp.Key;
textSecs.Remove(key);
textSecs.Add(key, sec);
}
}
The short answer is that there shouldn't be a way since a Dictionary "Represents a collection of keys and values." which does not imply any sort of ordering. Any hack you might find is outside the definition of the class and may be liable to change.
You should probably first ask yourself if a Dictionary is really called for in this situation, or if you can get away with using a List of KeyValuePairs.
Otherwise, something like this might be useful:
public class IndexableDictionary<T1, T2> : Dictionary<T1, T2>
{
private SortedDictionary<int, T1> _sortedKeys;
public IndexableDictionary()
{
_sortedKeys = new SortedDictionary<int, T1>();
}
public new void Add(T1 key, T2 value)
{
_sortedKeys.Add(_sortedKeys.Count + 1, key);
base.Add(key, value);
}
private IEnumerable<KeyValuePair<T1, T2>> Enumerable()
{
foreach (T1 key in _sortedKeys.Values)
{
yield return new KeyValuePair<T1, T2>(key, this[key]);
}
}
public new IEnumerator<KeyValuePair<T1, T2>> GetEnumerator()
{
return Enumerable().GetEnumerator();
}
public KeyValuePair<T1, T2> this[int index]
{
get
{
return new KeyValuePair<T1, T2> (_sortedKeys[index], base[_sortedKeys[index]]);
}
set
{
_sortedKeys[index] = value.Key;
base[value.Key] = value.Value;
}
}
}
With client code looking something like this:
static void Main(string[] args)
{
IndexableDictionary<string, string> fooDict = new IndexableDictionary<string, string>();
fooDict.Add("One", "One");
fooDict.Add("Two", "Two");
fooDict.Add("Three", "Three");
// Print One, Two, Three
foreach (KeyValuePair<string, string> kvp in fooDict)
Console.WriteLine(kvp.Value);
KeyValuePair<string, string> temp = fooDict[1];
fooDict[1] = fooDict[2];
fooDict[2] = temp;
// Print Two, One, Three
foreach (KeyValuePair<string, string> kvp in fooDict)
Console.WriteLine(kvp.Value);
Console.ReadLine();
}
UPDATE: For some reason it won't let me comment on my own answer.
Anyways, IndexableDictionary is different from OrderedDictionary in that
"The elements of an OrderedDictionary are not sorted in any way." So foreach's would not pay attention to the numerical indices
It is strongly typed, so you don't have to mess around with casting things out of DictionaryEntry structs

Best implementation for Key Value Pair Data Structure?

So I've been poking around with C# a bit lately, and all the Generic Collections have me a little confused. Say I wanted to represent a data structure where the head of a tree was a key value pair, and then there is one optional list of key value pairs below that (but no more levels than these). Would this be suitable?
public class TokenTree
{
public TokenTree()
{
/* I must admit to not fully understanding this,
* I got it from msdn. As far as I can tell, IDictionary is an
* interface, and Dictionary is the default implementation of
* that interface, right?
*/
SubPairs = new Dictionary<string, string>();
}
public string Key;
public string Value;
public IDictionary<string, string> SubPairs;
}
It's only really a simple shunt for passing around data.
There is an actual Data Type called KeyValuePair, use like this
KeyValuePair<string, string> myKeyValuePair = new KeyValuePair<string,string>("defaultkey", "defaultvalue");
One possible thing you could do is use the Dictionary object straight out of the box and then just extend it with your own modifications:
public class TokenTree : Dictionary<string, string>
{
public IDictionary<string, string> SubPairs;
}
This gives you the advantage of not having to enforce the rules of IDictionary for your Key (e.g., key uniqueness, etc).
And yup you got the concept of the constructor right :)
I think what you might be after (as a literal implementation of your question), is:
public class TokenTree
{
public TokenTree()
{
tree = new Dictionary<string, IDictionary<string,string>>();
}
IDictionary<string, IDictionary<string, string>> tree;
}
You did actually say a "list" of key-values in your question, so you might want to swap the inner IDictionary with a:
IList<KeyValuePair<string, string>>
There is a KeyValuePair built-in type. As a matter of fact, this is what the IDictionary is giving you access to when you iterate in it.
Also, this structure is hardly a tree, finding a more representative name might be a good exercise.
Just one thing to add to this (although I do think you have already had your question answered by others). In the interests of extensibility (since we all know it will happen at some point) you may want to check out the Composite Pattern This is ideal for working with "Tree-Like Structures"..
Like I said, I know you are only expecting one sub-level, but this could really be useful for you if you later need to extend ^_^
#Jay Mooney: A generic Dictionary class in .NET is actually a hash table, just with fixed types.
The code you've shown shouldn't convince anyone to use Hashtable instead of Dictionary, since both code pieces can be used for both types.
For hashtable:
foreach(object key in h.keys)
{
string keyAsString = key.ToString(); // btw, this is unnecessary
string valAsString = h[key].ToString();
System.Diagnostics.Debug.WriteLine(keyAsString + " " + valAsString);
}
For dictionary:
foreach(string key in d.keys)
{
string valAsString = d[key].ToString();
System.Diagnostics.Debug.WriteLine(key + " " + valAsString);
}
And just the same for the other one with KeyValuePair, just use the non-generic version for Hashtable, and the generic version for Dictionary.
So it's just as easy both ways, but Hashtable uses Object for both key and value, which means you will box all value types, and you don't have type safety, and Dictionary uses generic types and is thus better.
Dictionary Class is exactly what you want, correct.
You can declare the field directly as Dictionary, instead of IDictionary, but that's up to you.
Use something like this:
class Tree < T > : Dictionary < T, IList< Tree < T > > >
{
}
It's ugly, but I think it will give you what you want. Too bad KeyValuePair is sealed.

Categories