I want to append a string value in my dictionary in .net however I couldn't find an information about it for .net. Here is my dictionary which is set already with key-value pairs:
Dictionary<int, string> mydict = new Dictionary<int, string>();
I want to append new strings into existing ones in values.
For example: If we have <1,A> pair I want to append it to <1,AB>. Does anybody know a way to do this?
Well I am not sure what you trying to do, but let me guess: if you have key which exists, you want to append to the corresponding value, if not, insert new key-value pair? If so, see code bloew:
var key = 1;
var val = "new value to append";
if (myDict.CotainsKey(key))
{
myDict[key] += val;
}
else
{
myDict.Add(key, val);
}
Related
I want to create a Dictionary that have a multiple keys and when I want to get value using just one or more keys.
I tried :
Dictionary<Tuple<int, string>, string> dictionary = new Dictionary<Tuple<int, string>, string>();
var Key =new Tuple<int,string>(1,"I1");
var Value = "this is a value";
dictionary.Add(Key, Value);
When I try to get value from the dictionary I Must / Should enter all the keys
Like this :
MessageBox.Show($"{dictionary[new Tuple<int, string>(1,"I1")]}");
But when I try to get value using just one of keys like this
MessageBox.Show($"{dictionary[new Tuple<int, string>(1,"")]}");
I got error, I know that this error happened cause dictionary need the full exist key to return a value.
So please anyone have any Idea about how can I create a Dictionary with multiple keys and when retrieving value using just one or more or all keys ?
Dictionaries in .NET are expected to have close to O(1) lookup times. To achieve this, they make use of the GetHashCode() and Equals() methods of the key objects. The resulting hash code is used to divide the dictionary's contents into partitions. When you look up an item, the partition is identified using the hash code, all the items in that partition with a matching hash code* are compared to the key you're looking up using the Equals() method.
Here you are trying to create a dictionary with two keys for every object. You're doing this using a Tuple to make one key. The GetHashCode() result of a Tuple is based on both of its values, so the performance of a dictionary is lost if you want to look up values by only half of the key. You would need to go through the entire dictionary comparing each individual item, rendering it little better than a list.
One solution would be to make a dictionary that has a string->int key lookup, and then the other dictionary just be int->string. This would require two lookups when using string keys, but might be a good solution.
Example:
Dictionary<string, int> stringKeyToIntKey = new Dictionary<string, int>();
Dictionary<int, string> intKeyDict = new Dictionary<int, string>();
intKeyDict[1] = "Test";
stringKeyToIntKey["I1"] = 1;
Console.WriteLine(intKeyDict[1]);
Console.WriteLine(intKeyDict[stringKeyToIntKey["I1"]]);
An add method could look like this:
public void AddEntry(int intKey, string stringKey, string value)
{
intKeyDict[intKey] = value;
stringKeyToIntKey[stringKey] = intKey;
}
And you could wrap TryGetValue to make life easier:
public bool TryGetValue(string stringKey, out string value)
{
value = null;
return stringKeyToIntKey.TryGetValue(stringKey, out int intKey) && intKeyDict.TryGetValue(intKey, out value);
}
Delete would look like this:
public void DeleteEntry(string stringKey)
{
if (stringKeyToIntKey.TryGetValue(stringKey, out int intKey))
{
intKeyDict.Remove(intKey);
stringKeyToIntKey.Remove(stringKey);
}
}
You would have to make sure that items are added and removed from both dictionaries at the same time. When you add an item to intKey, you would need to add the corresponding key mapping to stringKeyToIntKey.
Alternatively, you could have two dictionaries: one with a string key and one with an int key, and each would have the same values. Again you would have to add and remove items at the same time, and you would also have to update the values in both at the same time.
Example:
Dictionary<string, string> stringKeyDict = new Dictionary<string, string>();
Dictionary<int, string> intKeyDict = new Dictionary<int, string>();
stringKeyDict["I1"] = "hello";
intKeyDict[1] = "hello";
Console.WriteLine(stringKeyDict["I1"]);
Console.WriteLine(intKeyDict[1]);
This is my favoured approach where the values are class instances, since both dictionaries will reference the same class instances for my items, and thus changes to properties of those instances will be reflected in both. For strings, however, the first option might be better.
* Hash codes are not unique and multiple objects can potentially have the same hash code, even if their values are not the same
You can use string for dictionary keys. Let's say you want to create a key from int x = 5 and string y = "str". You can concat and split them with some separator, and create a key like this:
string key = $"{x}:{y}"
And let's say you want to get elements only by x. you can write something like this:
dictionary.Where(kvp=>kvp.Key.Contains($"{x}:"))
of course, it will not give elements in O(1) time(it will give you elements in O(n) time) but it will work. If you want to get elements in O(1) time only by x I am not sure if it's possible with one dictionary.
this is my code
pritvate static Dictionary<int, string[]> _list = new Dictionary<int, string[]>();
how can i get the string[] out of this?
I have tried this and a lot more:
string[] s = _list.Values;
but it is all not working.
please help
If you want all string arrays for all keys merged into a single array, you can use LINQ's .SelectMany(...):
var strings = _list.Values.SelectMany(v => v).ToArray()
Reading your question again, I wonder if you're asking how to access a value for a single key. So, if you want the string array for a single key you can simply use the indexer:
var value = _list["keyname"];
But that will cause an exception if the key doesn't exist. If you're not sure that the key exists, you can use .TryGetValue(...):
string[] value;
if (_list.TryGetValue("keyname", out value))
{
// value was found
}
else
{
// value wasn't found
}
I have an output of a method that provides two key pieces of data per result.
Eg: 20160503 and nzdusd.
How can I store this in a dictionary and the sort against either one?
I want to be able to sort against key or value but can't get past adding the data!
Is there another data structure better suited?
Previously I tried simply calling Add()
But got an ArgumentException with message, An item with the same key has already been added..
Dictionary<string, string> missingDays = new Dictionary<string, string>();
// Some logic
missingDays.Add(formattedDate, fxPair); // Exception here
foreach (var missingDay in missingDays)
{
Console.WriteLine(missingDay);
}
A dictionary must have unique key values. In this case the formattedDate variable is being assigned the same value more than once, which causes an exception the second time you try to add an entry to the dictionary with the same formattedDate value.
You can use a Tuple<string, string> inside a list (List<Tuple<string, string>>) to store the values, and then use the LINQ method OrderBy() to sort the list.
var missingDays = new List<Tuple<string, string>>();
missingDays.Add(Tuple.Create("exampleFormattedDate", "exampleFxPair"));
foreach (var missingDay in missingDays.OrderBy(md => md.Item1))
{
Console.WriteLine(missingDay);
}
I am not a particularly confident programmer yet but am getting there.
My problem is that I have a
static Dictionary<string, Dictionary<string, List<string>>> testDictionary = ...
If the Dictionary doesn't contain the current key (string), I can easily add the key and another dictionary that has been populated, like so...
testDictionary.Add(userAgentResult, allowDisallowDictionary);
That works fine, my problem comes when I am trying to add the inner dictionary if the userAgentResult Key already exists.
I was hoping to do it this way...
testDictionary[userAgentResult].Add(allowDisallowDictionary);
but the .Add method wants two arguments, i.e. the string key and list value. So I went on to write this code...
//this list as the dictionary requires a list
List<string> testDictionaryList = new List<string>();
//this method returns a string
testDictionaryList.Add(regexForm(allowResult, url));
//this will add the key and value to the inner dictionary, the value, and then
//add this value at the userAgentKey
testDictionary[userAgentResult].Add(allowDisallowKey, testDictionaryList);
This also works, my problem is that this dictionary is added to numerous times, and when the inner dictionary already contains the key that is trying to be added, it obviously errors. So when
I would probably simplify this by having one dictionary and joining the keys thus "simulating" a grouping.
string key = userAgentResult + allowDisallowKey;
static Dictionary<string, List<string> testDictionary = ...
testDictionary[key] = list;
You simply need to manage one dictionary.
In this case what you need to do is not adding an entry to the inner dictionary. You need to add the value to the key-value pair of the outer dictionary. Only this time the value happens to be yet another dictionary :)
testDictionary[userAgentResult] = allowDisallowDictionary;
Maybe i don't get your problem. First make sure that dictionaries exist like so:
if (!testDictionary.ContainsKey(userAgentResult))
testDictionary[userAgentResult] = new Dictionary<string, List<string>>();
if (!testDictionary[userAgentResult].ContainsKey(allowDisallowKey))
testDictionary[userAgentResult][allowDisallowKey] = new List<string>();
Then you are free to add items like so:
testDictionary[userAgentResult][allowDisallowKey].Add("some value");
testDictionary[userAgentResult][allowDisallowKey].AddRange(someValueList);
When using nested dictionaries i normally use this approach:
private static Dictionary<string, Dictionary<string, List<string>>> _NestedDictionary = new Dictionary<string, Dictionary<string, List<string>>>();
private void DoSomething()
{
var outerKey = "My outer key";
var innerKey = "My inner key";
Dictionary<string, List<string>> innerDictionary = null;
List<string> listOfInnerDictionary = null;
// Check if we already have a dictionary for this key.
if (!_NestedDictionary.TryGetValue(outerKey, out innerDictionary))
{
// So we need to create one
innerDictionary = new Dictionary<string, List<string>>();
_NestedDictionary.Add(outerKey, innerDictionary);
}
// Check if the inner dict has the desired key
if (!innerDictionary.TryGetValue(innerKey, out listOfInnerDictionary))
{
// So we need to create it
listOfInnerDictionary = new List<string>();
innerDictionary.Add(innerKey, listOfInnerDictionary);
}
// Do whatever you like to do with the list
Console.WriteLine(innerKey + ":");
foreach (var item in listOfInnerDictionary)
{
Console.WriteLine(" " + item);
}
}
You need to do the same for the inner dictionary that you did for the outer one. First check if a list already exists for this key. If not create it. Then use the list that either existed or was created.
I use this:
foreach(KeyValuePair<String,String> entry in MyDic)
{
// do something with entry.Value or entry.Key
}
The problem is that I can't change the value of entry.Value or entry.Key
My question is that how can i change the value or key when looping through a dictionary?
And, does dictionary allow duplicated key? And if yes, how can we avoid ?
Thank you
You cannot change the value of a dictionary entry while looping through the items in the dictionary, although you can modify a property on the value if it's an instance of a reference type.
For example,
public class MyClass
{
public int SomeNumber { get; set;}
}
foreach(KeyValuePair<string, MyClass> entry in myDict)
{
entry.Value.SomeNumber = 3; // is okay
myDict[entry.Key] = new MyClass(); // is not okay
}
Trying to modify a dictionary (or any collection) while looping through its elements will result in an InvalidOperationException saying the collection was modified.
To answer your specific questions,
My question is that how can i change the value or key when looping through a dictionary?
The approach to both will be pretty much the same. You can either loop over a copy of the dictionary as Anthony Pengram said in his answer, or you can loop once through all the items to figure out which ones you need to modify and then loop again through a list of those items:
List<string> keysToChange = new List<string>();
foreach(KeyValuePair<string, string> entry in myDict)
{
if(...) // some check to see if it's an item you want to act on
{
keysToChange.Add(entry.Key);
}
}
foreach(string key in keysToChange)
{
myDict[key] = "new value";
// or "rename" a key
myDict["new key"] = myDict[key];
myDict.Remove(key);
}
And, does dictionary allow duplicated key? And if yes, how can we avoid ?
A dictionary does not allow duplicate keys. If you want a collection of <string, string> pairs that does, check out NameValueCollection.
Updating the dictionary in the loop is going to be a problem, as you cannot modify the dictionary as it is being enumerated. However, you can work around this pretty easily by converting the dictionary to a list of KeyValuePair<> objects. You enumerate that list, and then you can modify the dictionary.
foreach (var pair in dictionary.ToList())
{
// to update the value
dictionary[pair.Key] = "Some New Value";
// or to change the key => remove it and add something new
dictionary.Remove(pair.Key);
dictionary.Add("Some New Key", pair.Value);
}
For the second part, the key in a dictionary must be unique.
KeyValuePair's Key and value are read only. But you can change a value like that:
dictionary[key].Value = newValue;
But if you want to change the key, you will have to remove/add a key.
And no, a Dictionary does not allow duplicate keys, it will throw an ArgumentException.
You cannot modify keys while enumerating them.
One method I use for changes to the collection while enumerating them is that I do break; out of the foreach loop when a match is found and item is modified, and am restarting the whole enumeration all over again. That's one way of handling it...
No, Dictionary can't have duplicate keys. If you want something that will sort by key and allow duplicates, you should use some other data structure.
You can do this like
for (int i = 0; i < MyDic.Count; i++)
{
KeyValuePair<string, string> s = MyDic.ElementAt(i);
MyDic.Remove(s.Key);
MyDic.Add(s.Key, "NewValue");
}
And Dictionary doesn't allow duplicates