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);
Related
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 need to check if two lists have any elements in common. I just need a yes/no - I don't need the actual list of common elements.
I could use Enumerable.Intersect() but this does actually return the set of matching items which seems like it would require extra overhead. Is there a better method for checking if lists are disjoint?
My lists do actually happen to be List<T> but that isn't crucial and I could use something like HashSet (say) if that were more convenient. i.e., I don't want to unnecessarily constrain potential solutions.
Grazie mille
Simplest version (using Intersect):
public bool Compare(List<T> firstCollection, List<T> secondCollection)
{
return firstCollection.Intersect(secondCollection).Any();
}
Only caveat is either T shall implement IEquatable<T> or pass custom IEqualityComparer<T> in the Intersect call. Also make sure that GetHashCode is overriden along with Equals
Edit 1:
This version using Dictionary will not just provide boolean comparison, but also the elements. In this solution Dictionary in the end would contain data related to number of intersecting elements, number of elements in one of the collection but not in another, so fairly durable. This solution also has IEquatable<T> requirement
public bool CompareUsingDictionary(IEnumerable<T> firstCollection, IEnumerable<T> secondCollection)
{
// Implementation needs overiding GetHashCode methods of the object base class in the compared type
// Obviate initial test cases, if either collection equals null and other doesn't then return false. If both are null then return true.
if (firstCollection == null && secondCollection != null)
return false;
if (firstCollection != null && secondCollection == null)
return false;
if (firstCollection == null && secondCollection == null)
return true;
// Create a dictionary with key as Hashcode and value as number of occurences
var dictionary = new Dictionary<int, int>();
// If the value exists in first list , increase its count
foreach (T item in firstCollection)
{
// Get Hash for each item in the list
int hash = item.GetHashCode();
// If dictionary contains key then increment
if (dictionary.ContainsKey(hash))
{
dictionary[hash]++;
}
else
{
// Initialize he dictionary with value 1
dictionary.Add(hash, 1);
}
}
// If the value exists in second list , decrease its count
foreach (T item in secondCollection)
{
// Get Hash for each item in the list
int hash = item.GetHashCode();
// If dictionary contains key then decrement
if (dictionary.ContainsKey(hash))
{
dictionary[hash]--;
}
else
{
return false;
}
}
// Check whether any value is 0
return dictionary.Values.Any(numOfValues => numOfValues == 0);
}
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();
A standard dictionary would look like this:
public Dictionary<int, DictionarySetup> H = new Dictionary<int, DictionarySetup>()
{
{18000, new DictionarySetup { Some values }},
};
Ranging from A-T, all of these are in a class called DictionaryInit, right now I check the value if there's a match with this boolean:
public Boolean Dictionary_Test(Dictionary<int, DictionarySetup> AccountLexicon)
{
DictionarySetup ClassValues;
if (AccountLexicon.TryGetValue(MapKey, out ClassValues))
{
return true;
}
return false;
}
Now, I'm looking for a more efficient method to loop through each Dictionary and, if there's a match, get that particular dictionary for use in a subsequent method, this is what it looks like now in an if/else:
if(Dictionary_Test(theDictionary.C) == true)
{
Dictionary_Find(Account_String, rowindex, theBSDictionary.C, Cash_Value, txtCurrency.Text);
}
else if (Dictionary_Test(theDictionary.D) == true)
{
Dictionary_Find(Account_String, rowindex, theDictionary.D, Cash_Value, txtCurrency.Text); //Method that makes use of the dictionary values, above dictionary checks only if it exists
}
With dictionaries from A-T, that would be alot of if/else's! Is there a better way to do this? I've found one thread mentioning this same topic, by adding the dictionaries to a dictionary array[] then looping over it, but how do I get the name of the matching dictionary if a match is found or make my second method, Dictionary_Find, use the matching dictionary?
Another possible solution, you could use reflection to get each dictionary from A-T from the DictionaryInit class. Create an array that contains values A-T, loop through the array and use reflection to get the dictionary, and test that dictionary, if you find a match, return that dictionary and exit the loop. Something like:
var dicts = new[]{"A", "B", ......., "T"}
foreach (var dict in dicts)
{
var found = CheckDictionary(theDictionary, dict);
if (found != null)
{
Dictionary_Find(Account_String, rowindex, (Dictionary<int, DictionarySetup>)found, Cash_Value, txtCurrency.Text);
break;
}
}
public static object CheckDictionary(object dictClass, string dictName)
{
var theDictionary = dictClass.GetType().GetProperty(dictName).GetValue(dictClass, null);
return Dictionary_Test(theDictionary) ? theDictionary : null;
}
I've just quickly grabbed some code from a project I've done and modified it to suit but haven't tested it. Might need a few tweaks but hopefully gets you close!
// put dictionary A ~ T to a list of dictionary
List<Dictionary<int, DictionarySetup>> dictionaries = new List<Dictionary<int, DictionarySetup>>{A,B,C, ... , T}; // Replace ... with D,E,F, etc. until T
// iterate each dictionary and if found, exit the loop
foreach(var dict in dictionaries)
{
if(Dictionary_Test(dict))
{
Dictionary_Find(Account_String, rowindex, dict, Cash_Value, txtCurrency.Text);
break;
}
}
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.