An Upgrade on using a Predicate as a Key to a Dictionary

In an earlier post, I discussed using a Predicate<string> as a key to a Dictionary.
Dictionary<Predicate<string>, string> : that utilizes a where clause to determine TRUE.

This post is a slight upgrade to the concept where I make an (almost) 1-liner class and Extension Method that handles generics for both the subject-of-the-Predicate
as well as the Type of the Key and the Type of the value in the pseudo-Dictionary.

The Dictionary reference (ha ha) is used for syntax purposes and the actual implementation of something like this would expect the programmer to iterate through the collection rather than attempt a direct key-to-result attempt at the pseudo-Dictionary.

I changed this (15-SEP-2015) because a comment from a reader let me know my intention was not clear.

  Since it’s easier to show than explain:

using System;
using System.Collections.Generic;
using System.Linq;
namespace Predicize
	public static class CPredicize
		public static U Predicize<T, U>(this IEnumerable<KeyValuePair<Predicate<T>, U>> map, T keyCandidate)
			return map.Where(kvp => kvp.Key(keyCandidate)).First().Value;
This class exposes an extension method named Predicize that partners with an IEnumerable<KeyValuePair<Predicate<T>, U>> (like a Dictionary with a predicate of T as its key). 
Given an IEnumerable that meets the implied interface, the method will return the first value where the Predicate under the key returns true when executed.
It is up to the developer to ensure a default condition exists to prevent the construct from not successfully returning true.
using System;
using System.Collections.Generic;
using System.Linq;
namespace PlayWithPredicize
	using Predicize;
	class CPlayWithPredicize
		private static IEnumerable<KeyValuePair<Predicate<int>, string>> map_fni2strSpecial =
			new Dictionary<Predicate<int>, string> // <-- for syntax purposes only
			{i => i.Equals(4), "Good"},
			{i => i.Equals(5), "Super"},
			{i => i.Equals(7), "Perfect"},
			{i => i.Equals(9), "Fantastic"},
			{i => i.Equals(10), "Stupendous"},
			{i => true, "OK"},
		static void Main(string[] args)
					Enumerable.Range(0, 10)
					.Select(i =>
						string.Format("{0} = {1}", i, map_fni2strSpecial.Predicize(i))).ToArray())


The preceding code loops through the numbers 0-9 and matches those numbers with result of the call to the Predicize extension method.
Since, 0 will not be found in the dictionary, the result will be “OK”.  When 4 is encountered, it returns “Good”.
Here is the result of the full run:



The results are processed as strings, but could easily be any other type to include delegates/funcs/methods, etc.

posted @ Tuesday, September 8, 2015 4:29 PM

Comments on this entry:

# re: An Upgrade on using a Predicate as a Key to a Dictionary

Left by Thomas Levesque at 9/9/2015 12:13 PM
This is a pretty bad idea. The Dictionary<K, V> class makes no guarantees regarding the order of the entries. You expect the entry with the key "i => true" to be the last one, but it might not be the case.

Also, it doesn't take advantage at all of the dictionary's fast lookup (O(1)), since you just enumerate the entries (O(n)).

You could get the same result with a list (preferably wrapped in a custom class that exposes just the desired functionality), which would avoid the order problem mentioned above.

# re: An Upgrade on using a Predicate as a Key to a Dictionary

Left by Tom at 9/9/2015 12:48 PM
Thomas, the intention was not for this to be used like a regular dictionary -- that WOULD be bad. Yes, its use is that of a IEnumerable<KeyValuePair<Predicate<T>,U>>. There is no run-time checking of the keys and only compile-time checking if the Key/Predicate is static.

If the dictionary is dynamically created, the location of the keys will be determined by the framework.

Thanks for the feedback!

Your comment:

(not displayed)


Live Comment Preview: