I have two IEnumerable
IEnumerable<MyObject> allowedObjects = MyService.GetAllowedObjects();
IEnumerable<MyOBject> preferedObjects = MyService.GetPreferedObjects();
We can safely assume that preferedObjects will always be a subset of allowedObjects.
I want to create an IDictionary<MyObject, bool>
. Objects where the key is the set of MyObjects from the allowedObjects and the bool is true if the MyObject instance was also in the preferedObjects enumerable.
I can do this by enumerating them and adding them one by one, but I would like to be able to do something like this:
IDictionary<MyObject, bool> selectedObjects = allowedObjects
.ToDictionary(o => new KeyValuePair<MyObject, bool>()
{ Key = q,
Value = preferedObjects.Any(q)
}
);
UPDATE
Exchanged Contains with Any;
The solution that is suggested most was what I tried first, but it isn't accepted for some reason:
IDictionary<MyObject, bool> selectedObjects = allowedObjects
.ToDictionary<MyObject, bool>(o => o, preferedObjects.Any(o));
Visual studio says the first method does not return a bool. Which is true, but mainly because a bool would not be the correct result to start with...
And then it says it cannot infere the type of the second lambda...
As you can see I tried to explicitly define the types to help the inference, but it doesn't solve a thing..
Suggestions?
Disclaimer: names and code are snippyfied to keep the focus where it should be
In LINQ, ToDictionary() Method is used to convert the items of list/collection(IEnumerable<T>) to new dictionary object (Dictionary<TKey,TValue>) and it will optimize the list/collection items by required values only.
The ToDictionary method is an extension method in C# and converts a collection into Dictionary.
The formula for calculating lambda is: Lambda = (E1 – E2) / E1. Lambda may range in value from 0.0 to 1.0. Zero indicates that there is nothing to be gained by using the independent variable to predict the dependent variable. In other words, the independent variable does not, in any way, predict the dependent variable.
I can't remember whether Linq provides a "Contains" extension method on IEnumerable<T>
. If not, you could use Any:
var dict = allowedObjects.ToDictionary(o => o,
o => preferredObjects.Contains(o));
** Edit ** Yep, just tested it and there is indeed a Contains() extension method, so the above code works.
Enumerable.ToDictionary
has multiple overloads. Some of these take a second delegate (so you can pass a lambda) to return the value to go with the key.
Something like:
var secondDict = firstDictionary
.Where(p => SomeCondition(p))
.ToDictionary(p => p.Key, p => p.Value);
You're almost there:
IDictionary<MyObject, bool> selectedObjects = allowedObjects
.ToDictionary(o => o, o => preferedObjects.Contains(q));
The ToDictionary
extension method works around using two lambda expressions to generate the key/value pair rather than the KeyValuePair
type.
You could speed things dramatically by using HashSet<T>
objects for your allowedObjects
and preferredObjects
collections, though I wouldn't bother unless your lists are especially large/performance is important.
You can of course create your own extension method. ToDictionary simply creates a dictionary by adding all elements in the source as values and using a lambda as key. You can create your own with a different approach. As you use 'contains' I don't think it's a good idea to do it that way, as it is a slow operation (linear search, for every element in allowedObjects, you're enumerating preferredobjects).
One approach could be to add all preferredobjects to a HashSet and use Contains on that. Another could be to use a linq query where you join actualObjects with preferredObjects, using join into, and use DefaultIfEmpty. This is more efficient:
List<MyObject> allowedObjects = new List<MyObject>() { new MyObject("one"), new MyObject("two"), new MyObject("three")};
List<MyObject> preferredObjects = allowedObjects.Take(2).ToList();
var q = from a in allowedObjects
join p in preferredObjects on a equals p into ap
from x in ap.DefaultIfEmpty()
let isPreferred = (x != null)
let toUse = x ?? a
select new { toUse, isPreferred };
Dictionary<MyObject, bool> selectedObjects = new Dictionary<MyObject, bool>();
foreach(var v in q)
{
selectedObjects.Add(v.toUse, v.isPreferred);
Console.WriteLine("{0}, {1}", v.toUse.Foo, v.isPreferred);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With