I have a list of dictionary and i am searching for a key based on value. How to do this?
"someId" returns an error:
"The given key was not present in the dictionary."
So if I give value "Ann", then I would expect the function to return key "30".
Each Item in the dictionary is like this
item 1
[0] {[someid,30]}
[1] {[somename,"Ann"]}
[2] {[someaddress,"3, Carl House, UK"]}
private static int getmyId(string name)
{
...
List<Dictionary<string, string>> myList = new List<Dictionary<string, string>>();
foreach (Dictionary<string, string> item in myList)
{
if (item.ContainsValue(name))
{
myID = item["Someid"];
}
}
...
return myID
}
To get a key from a value in a dictionary is a bit tricky because values can be reused. Therefore you either need to return a list of keys, or have the function only return the first matching key.
Here's both methods as static functions:
static List<string> GetKeysFromValue(Dictionary<string,string> dict, string val)
{
if(!dict.ContainsValue(val))
return new List<string>(); //return EMPTY list for no matching keys
return dict.Where(kv => kv.Value.Equals(val)).Select(kv => kv.Key).ToList();
}
To explain the above:
We get all the key-value pairs in the dictionary that have the matching value using the Where linq function.
Now that we have an IEnumerable of KeyValuePair objects we then call Select, which is a linq function that performs projections. This takes the keys out of the returned IEnumerable<KeyValuePair>.
Finally, we convert the IEnumerable<string> to a list by calling .ToList()
To get only the first matching key, you can do this:
static string GetFirstKeyFromValue(Dictionary<string,string> dict, string val)
{
if(!dict.ContainsValue(val))
return null; //return null because nothing matched.
return dict.FirstOrDefault(kv => kv.Value.Equals(val)).Key;
}
FirstOrDefault will return the first matching key value pair from the dictionary, or null if none are found. Since we already checked that it will return something earlier with the ContainsValue() method, we can safely just call Key to get the value of the key property.
I also wanted to point out that based on your method signature that you posted you are treating your Dictionary<string,string> as a List<string>. A dictionary does not have indexes, hence the use of a user-defined key type. Therefore there is no reason to return an int since there is no index. Instead you should be returning the key, which you posted is a string.
Related
I am trying to get my method to return a matchKey's value as I pass this to the method but the value is returning as Null. Also it shows my dictionary contains the Key and the value i am looking for also my if(Items.TryGetValue(item.Key.Contains(matchKey).ToString() returns true but it does not add it to the second dictionary I have.. My Items dictionary has all the key and values and I am able to return that.. but I am trying to extract one of the key which is "id" and its value "80" from that and adding to my second dictionary keyValues and returning that if it contains..
Here is the Json after Serializing
{"UserId":"","UserId2":"","id":"80"}
public Dictionary<string, string> GetKeyAndValues(string matchKey)
{
string data = JsonConvert.SerializeObject(dataEntries);
Dictionary<string, string> Items = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
Dictionary<string, string> keyValues = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> item in Items)
{
if (!Items.ContainsKey(item.Key))
{
Items.Add(item.Key.ToString(), item.Value.ToString());
}
var value = Items[matchKey];
if(Items.TryGetValue(item.Key.Contains(matchKey).ToString(), out value))
{
keyValues.Add(matchKey, value);
return keyValues;
}
}
return Items;
}
The major problem in your code is in this line of code:
if (Items.TryGetValue(item.Key.Contains(matchKey).ToString(), out value))
It doesn't check if an item with the key matchKey is contained in the Items dictionary. This sub-expression item.Key.Contains(matchKey) checks if matchKey is contained in the Items and returns true or false. Therefore this problem line checks if a key with value true of false is contained in the Items.
Here is a fixed method GetKeyAndValues:
public static Dictionary<string, string> GetKeyAndValues(string matchKey)
{
string data = JsonConvert.SerializeObject(dataEntries);
Dictionary<string, string> Items = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
// We don't need a loop to check if a key "matchKey" is contained in the "Items".
// Items.TryGetValue(matchKey, out string value) checks if "matchKey" is contained
// in the "Items", and if it is contained it returns an appropriate "value".
if (Items.TryGetValue(matchKey, out string value))
{
// Here we create a Dictionary with a single pair (matchKey, value).
return new Dictionary<string, string> {{matchKey, value}};
}
return Items;
}
Here is a useful link to the documentation of the method Dictionary.TryGetValue.
I've currently had to put some data in dictionary, to check whether some of the actual data, match the expected one for some of my tests.
For the task I've created a Dictionary that looked somehow like that:
Dictionary<string, string> dict = new Dictionary<string, string>(){
{a, a},
{b, b},
{c, c}
};
The first that I've tried was to compare the Dictionary Values and Keys in conditional statement like shown below and I was kinda suprised with the false result of this conditional statement:
if(dict.Keys.Equals(dict.Values)) {
///// received false as a result here //////
}
When I then tried the next approach which was to iterate through all of dictionary items and to compare each of their Value Key pairs, it suddenly resulted in giving me the expected (true) result for all items of Dictionary:
foreach (var item in dict) {
if (item.Key.Equals(item.Value))
{
///// received true as a result /////
}
else { other code here }
}
Why did I get the false result for the first approach described?
You expect them both to be an ICollection if you look into the docs.
Have a look in the reference source of the dictionary class.
The Keys and Values Properties are implemented using different collection-types.
// Line 135
public KeyCollection Keys {
get {
Contract.Ensures(Contract.Result<KeyCollection>() != null);
if (keys == null) keys = new KeyCollection(this);
return keys;
}
}
// Line 157
public ValueCollection Values {
get {
Contract.Ensures(Contract.Result<ValueCollection>() != null);
if (values == null) values = new ValueCollection(this);
return values;
}
}
Also if you look into the KeyCollection and ValueCollection Classes, you will notice, that there is no other implementation of the Equals() Method. As those classes don't derive from any other class, you may be sure that dict.Keys.Equals(dict.Values) will call the object.Equals() Method.
This call will obviously return false.
I have a dictionary fooDictionary<string, MyObject>.
I am filtering the fooDictionary to get only the MyObject with a specific value of the property.
//(Extension method is a extension method that I made for the lists
//(PS: ExtensionMethod returns only 1x MyObject))
fooDictionary.Values.Where(x=>x.Boo==false).ToList().ExtensionMethod();
But I also want to get the keys of the already filtered MyObject's. How can I do that?
Instead of just pulling the values, query the KeyValuePair
fooDictionary.Where(x => !x.Value.Boo).ToList();
This will give you all the key value pairs where the MyObject has a Boo value of false.
Note: I changed your line x.Value.Boo == false to !x.Value.Boo as that is the more common syntax and is (IMHO) easier to read/understand the intent.
EDIT
Based on you updating the question to change from dealing with a list to this new ExtensionMethod here is an updated answer (I am leaving the rest as is as it answers what the original posted question was).
// Note this is assuming you can use the new ValueTuples, if not
// then you can change the return to Tuple<string, MyObject>
public static (string key, MyObject myObject) ExtensionMethod(this IEnumerable<KeyValuePair<string, MyObject>> items)
{
// Do whatever it was you were doing here in the original code
// except now you are operating on KeyValuePair objects which give
// you both the object and the key
foreach(var pair in items)
{
if ( YourCondition ) return (pair.Key, pair.Value);
}
}
And use it like this
(string key, MyObject myObject) = fooDictionary.Where(x => !x.Value.Boo).ExtensionMethod();
I saw many similar questions, however didn't find exactly what I need here. Any help appreciated.
I have set of Keys (K[1..M]), each Key K[i] can be mapped to any value from a set of available values for this particular Key K[i]:V[i,1..Ni]
K[1]: V[1,1] | V[1,2] ... | V[1,N1]
K[2]: V[2,1] | V[2,2] ... | V[1,N2]
...
K[M]: V[M,1] | V[M,2] ... | V[1,NM]
I need to implement RECURSIVE function returning enumerable of all possible combinations of K-V mappings
For example:
With given set:
K1: 1 | 2 | 3
K2: 4 | 1
Combinations will be the following:
(K1:1, K2:4)
(K1:2, K2:4)
(K1:3, K2:4)
(K1:1, K2:1)
(K1:2, K2:1)
(K1:3, K2:1)
Ideally the function should be like this:
IEnumerable<Dictionary<TKey, TValue>> EnumerateAllPossibleCombinations(IEnumerable<TKey> keys, Func<TKey, IEnumerable<TValue>> getAvailableValuesForKey)
{
...
yield return ...;
}
Using of function (draft code):
var allCombinations = EnumerateAllPossibleCombinations<string, int>(new[]{"K1","K2"}, k=>{
switch k
{
case "K1": return new[]{1,2,3};
case "K2": return new[]{4,1};
}
ThrowException("Unknown key");
});
Result for example above should be 6 dictionaries with 2 key-value-pairs in each
I'm trying to avoid using Cartesian Product, since I need to receive dictionary after dictionary (allCombinations.ElementAt(1), allCombinations.ElementAt(2)), while Cartesian has to be executed entirely for all combinations before it can return first dictionary.
I believe this is what you are looking for.
public static IEnumerable<IDictionary<TKey, TSource>> EnumerateAllPossibleCombinations<TKey, TSource>(
IEnumerable<TKey> keys,
Func<TKey, IEnumerable<TSource>> getAvailableValuesForKey)
{
if (keys == null)
{
throw new ArgumentNullException("keys");
}
if (getAvailableValuesForKey == null)
{
throw new ArgumentNullException("getAvailableValuesForKey");
}
return keys.Any() ?
EnumerateAllPossibleCombinationsImp(keys.Distinct(), getAvailableValuesForKey) :
Enumerable.Empty<IDictionary<TKey, TSource>>();
}
private static IEnumerable<IDictionary<TKey, TSource>> EnumerateAllPossibleCombinationsImp<TKey, TSource>(
IEnumerable<TKey> keys,
Func<TKey, IEnumerable<TSource>> getAvailableValuesForKey)
{
if (!keys.Any())
{
yield return new Dictionary<TKey, TSource>();
yield break;
}
var firstKey = keys.First();
var values = getAvailableValuesForKey(firstKey) ?? Enumerable.Empty<TSource>();
bool hasValues = values.Any();
foreach (var value in values.DefaultIfEmpty())
{
foreach (var dictionary in EnumerateAllPossibleCombinationsImp(keys.Skip(1), getAvailableValuesForKey))
{
if (hasValues)
{
dictionary.Add(firstKey, value);
}
yield return dictionary;
}
}
}
First the reason for two methods is so the ArgumentNullExceptions for keys and getAvailableValuesForKey will be thrown when the method is called instead of when the resulting IEnumerable is iterated. Next we do a quick check to see if keys is empty and if it is we just return an empty IEnumerable. If it is not empty then we call the second method that contains the main implementation.
The second method is recursive, so first we setup our default case which is keys being empty in which case we yield an empty dictionary (This is why we do the empty check in the first method). Then we break the problem down by taking the first item from keys and retrieve the values for that key. If getAvailableValuesForKey returns null for that key we will treat it as if it returned an empty set instead (this could instead be treated as an exception case if desired). We then check to see if there are any values and we iterate over them, but in the case that there are none we use DefaultIfEmpty to insert one default value. That is done so that we will do one iteration for an empty set of values. Then we do a recursive call passing in the rest of the keys by use Skip(1) and for each returned dictionary we check if we had any values for the key and if we did then we add that key and value pair to the dictionary and either way we yield the dictionary. The idea is that eventually the recursive calls will hit the case where there are no keys and just return an empty dictionary that will then have entries added to it as the recursive calls unwind.
Your solution will essentially take the form of (pseudocode):
foreach (var key in dictionary)
foreach (var value in dictionary)
yield return new KeyValuePair(key, value)
If you need to pass in a predicate to constrain the values, you can insert it thusly:
foreach (var key in dictionary)
foreach (var value in getAvailableValuesForKey)
yield return new KeyValuePair(key, value)
The actual code will look closer to this (untested):
foreach (var x in dictionary)
foreach (var y in dictionary)
yield return new KeyValuePair (x.key, y.value);
Here is my code:
string[] inputs = new[] {"1:2","5:90","7:12","1:70","29:60"};
//Declare Dictionary
var results = new Dictionary<int, int>();
//Dictionary<int, int> results = new Dictionary<int, int>();
foreach(string pair in inputs)
{
string[] split = pair.Split(':');
int key = int.Parse(split[0]);
int value = int.Parse(split[1]);
//Check for duplicate of the current ID being checked
if (results.ContainsKey(key))
{
//If the current ID being checked is already in the Dictionary the Qty will be added
//Dictionary gets Key=key and the Value=value; A new Key and Value is inserted inside the Dictionary
results[key] = results[key] + value;
}
else
{
//if No duplicate is found just add the ID and Qty inside the Dictionary
results[key] = value;
//results.Add(key,value);
}
}
var outputs = new List<string>();
foreach(var kvp in results)
{
outputs.Add(string.Format("{0}:{1}", kvp.Key, kvp.Value));
}
// Turn this back into an array
string[] final = outputs.ToArray();
foreach(string s in final)
{
Console.WriteLine(s);
}
Console.ReadKey();
I want to know if the difference if there is between assigning a key=>value pair in a dictionary.
Method1:
results[key] = value;
Method2:
results.Add(key,value);
In method 1, the function Add() was not called but instead the Dictionary named 'results' assigns somehow sets a Key-Value pair by stating code in method1, I assume that it somehow adds the key and value inside the dictionary automatically without Add() being called.
I'm asking this because I'm currently a student and I'm studying C# right now.
Sir/Ma'am, your answers would be of great help and be very much appreciated. Thank you++
The Dictionary<TKey, TValue> indexer's set method (the one that is called when you do results[key] = value;) looks like:
set
{
this.Insert(key, value, false);
}
The Add method looks like:
public void Add(TKey key, TValue value)
{
this.Insert(key, value, true);
}
The only difference being if the third parameter is true, it'll throw an exception if the key already exists.
Side note: A decompiler is the .NET developers second best friend (the first of course being the debugger). This answer came from opening mscorlib in ILSpy.
If the key exists in 1) the value is overwritten. But in 2) it would throw an exception as keys need to be unique