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);
}
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.
I have a question about how to get values from my Dictionary<string, List<object>>, I tried all examples which I found in google, but still can't get something readable value.....
so, here is the code:
List<object> listValues = new List<object>();
listValues.Add(risk);
listValues.Add(validFrom);
listValues.Add(effectiveDate);
Dictionary<string, List<object>> dic = new Dictionary<string, List<object>>();
dic.Add(nameOfInsuredObject, listValues);
foreach (object value in dic.Values)
{
System.Console.WriteLine(value);
}
I can get key from dictionary, but with getting value I am stucked now....
And here is the result of this code:
Key => testInsObj
Values => System.Collections.Generic.List`1[System.Object]
So can anyone help me with it? I am new in C#, so maybe this is easy questions for others....
It seems you are looking for writing values of the list this way:
foreach (var value in dic.Values)
{
value.ForEach(Console.WriteLine);
}
In fact each element of the Dictionary is <string, List<Object>>. So, when you want to write Value part of the pair to console, you need a for loop to write each element of the List<object>.
It is confusing for new C# users, how to access the dictionary.
When you do a foreach on the dictionary, you get a KeyValuePair<TKey, TValue>. Now this KeyValuePair<TKey, TValue>, has 2 properties KeyValuePair.Key and KeyValuePair.Value, representing the Key and Value stored in the dictionary.
Also, the Value in your case is a List<T>, which means doing a Console.WriteLine on it will not print the whole List<T> (as some people expect), but just some reference string. You will have to "loop" over the list to print individual elements. Needless to say, depending on what you want to do with the element in the List<T>, you can use LINQ or some other common C# idiom.
foreach (var value in dic) {
Console.WriteLine(value.Key);
foreach (var item in value.Value)
Console.WriteLine(item);
}
I have a problem with copying the values of the numbers into another dictionary.
Everything goes well, but as soon as I add values from a List to another dictionary if the key already exists. I do not understand how it is possible that the same values are added to the dictionary as well as going through.
foreach (KeyValuePair<string, List<int>> record in dictonaryUnStem)
{
arrayWord = record.Key.ToCharArray();
st.add(arrayWord);
stemWord = st.stem();
if (!dictonaryStem.ContainsKey(stemWord))
{
dictonaryStem.Add(stemWord, record.Value);
}
else
{
foreach (int i in record.Value)
{
dictonaryStem[stemWord].Add(i);
}
}
}
When you add to another dictionary from the given key integers. We join me on the record, too integers dictionaryUnStem. It is a complete illogical.
stemWord = st.stem()
gives me root word which is the key word in the first dictionary. In the list are stored position of that words in the text.
The problem is here:
dictonaryStem.Add(stemWord, record.Value);
You are setting the dictionary value to the reference of the original list (List<T> is a reference type) - hence when you add an item to that list, it also shows up in the dictionary - both reference the same list.
Instead you can just force creation of a new list for your dictionary:
dictonaryStem.Add(stemWord, record.Value.ToList());
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 have a text file with the following structure
01|value|value|value|value|value|value
02|value|value|value|value|value|value
03A|value|value|value|value|value|value
03A|value|value|value|value|value|value
.
.
N
04|value|value|value|value|value|value
05|value|value|value|value|value|value
06|value|value|value|value|value|value
.
.
N (variable lines)
I tried to read the text file and add it to a dictionary of type <string, string[]> in order to use it like MyDic["01"][0], this is a fragment of the code:
Dictionary<string, string[]> txtFromFile= new Dictionary<string, string[]>();
string strLine;
using (StreamReader sr = new StreamReader(filePath))
{
while ((strLine= sr.ReadLine()) != null)
{
string[] strNodes= strLine.Split('|');
txtFromFile.Add(strNodes[0], strNodes);
}
}
Unfortunately, as you can see, this text file could have duplicated keys like 03A, so I was wondering if there's a collection in c# to achieve this.
NOTE I saw a class named lookup, but there's no constructor for it.
Any thoughts my friends?
What do you suggest?
Thanks!
Why not just create a class like
public class MyLine
{
string key { get;set;}
string[] value {get;set;}
}
and store it in a geneirc List
then you can use linq to query whatever you want ...
You can use the ToLookup extension method:
string[] lines = File.ReadAllLines(filePath);
ILookup<string, string[]> result = lines
.Select(line => line.Split('|'))
.ToLookup(parts => parts[0]);
The first problem is that you are trying to use the wrong type, if you are concerned with multiple entries with the same key. You can achieve this with a List<KeyValuePair<string, string[]>> and your own lookup function, likely through extending the class, or you can add another dictionary inside the dictionary as your value type: Dictionary<string, Dictionary<int, string[]>>. The Dictionary option is the better bet as it has better performance.
How about a List with a custom type?
class KeyValue
{
String ID { get ; set ; }
List<String> Values { get ; private set ;}
(..Constructor etc...)
}
List<KeyValue> myValues = new List<KeyValue>();
while ((strLine= sr.ReadLine()) != null)
{
string[] strNodes= strLine.Split('|');
myValues.Add(new KeyValue(strNodes[0],strNodes));
}
You could use List<KeyValuePair<string, string[]>> or List<Tuple<string, string[]>>
(And of course you might prefer a different collection type instead of List<>)
I'm not sure if you're trying to distinguish between values on the first 03A line from values on the second 03A line, but I think you're looking for a NameValueCollection. NameValueCollections allow you to add multiple values to the same key, and the Add() method should check for pre-existing keys before appending the values/creating a new key/value entry.
There's a good example of the way to use the NameValueCollection at the bottom of that MSDN reference article, so you should be able to use that to determine if it's what you really need.
Another thought would be to use
Dictionary<string, List<string[]>>
Where "string" is the value that might be repeated. When it gets repeated, you create another Dictionary inside. If a row exists once, it will have one List. If a duplicate row is found, add another. In this way, you can see how many duplicate rows there were just by count of Lists.