i want to check for the occurrence of some given items in the collection and thought it work like this but it doesn't
public static bool ContainsAny<T>(this IEnumerable<T> collection, IEnumerable<T> otherCollection)
{
if (otherCollection == null)
throw new ArgumentNullException("otherCollection", ExceptionResources.NullParameterUsed);
if (collection == null)
throw new ArgumentNullException("collection", ExceptionResources.ExtensionUsedOnNull);
else
return Enumerable.Any<T>(otherCollection, new Func<T, bool>(((Enumerable)collection).Contains<T>));
}
I want to get true if the specified collection contains any of the otherCollection items, otherwise false.
But there is an error telling me that i can not convert system.collections.generic.iEnumerable>T> in system.linq.Enumberable. Where is my mistake?
This should work:
return otherCollection.Any(collection.Contains);
You don't need any cast to call Contains method,because there is already an extension method that takes an IEnumerable<T> as first parameter.
Related
I want to create an extension method that runs on a List and accept another list:
public static void Charge<T, S>(this ICollection<T> targetList, ICollection<S> sourceList) where T : class, new()
{
if (targetList == null || sourceList == null)
throw new NullReferenceException();
targetList = new List<T>();
foreach (var item in sourceList)
{
T t = new T();
//do work on t
targetList.Add(t);
}
}
however when I call it like this:
var targetList = new List<Item>();
targetList.Charge(sourceList);
the targetList doesn't change (items count = 0)
The proposed method makes no sense to me.
You want to copy the contents of the source list into the target, but you first want to replace the target list to make sure it's empty? If you're going to replace the target list anyway, why not simply replace it like so?
target = source.ToList();
Also, how do you propose to implement the "do some work on t" in a generic extension method where the types of S and T are not known? Why not do the idiomatic thing, e.g.:
target = source.Select(s => Transform(s)).ToList();
Here, we assume Transform is a method capable of creating and populating a target object from a source object.
Or, you could avoid reallocating a new list by clearing the old one first:
target.Clear();
target.AddRange(source.Select(s => Transform(s)));
And if you really want to have a single invocation, you could simply wrap either of the alternatives above, e.g.:
public static List<TTarget> ToList<TSource, TTarget>(
this IEnumerable<TSource> source,
Func<TSource, TTarget> conversion)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (conversion == null)
throw new ArgumentNullException(nameof(conversion));
return source.Select(conversion).ToList();
}
Usage:
target = source.ToList(s => Transform(s));
You can't assign a new instance to targetList if you pass the list by value. You can add or remove or modify the content of the existing list, but if you want to assign another instance you need to add the ref keyword to allow assignments.
I have a situation where I need a generic method to which I can pass two collections of type T along with a delegate that compares the two collections and returns true if every element in collection 1 has an equal element in collection 2, even if they are not in the same index of the collection. What I mean by "equal" is handled by the delegate. My initial thought was to return false if the collections were different lengths and otherwise sort them and then compare them like parallel arrays. Then it occurred to me that I can't sort a collection of a generic type without the types sharing an interface. So now I am thinking a LINQ expression might do the trick, but I can't think of how to write it. Consider my current code:
private static bool HasSameCollectionItems<T>(ICollection<T> left, ICollection<T> right, Func<T, T, bool> func)
{
if (left.Count != right.Count)
{
return false;
}
foreach (var item in left)
{
bool leftItemIsInRightCollection = ??? MAGIC ???
if (!leftItemIsInRightCollection)
{
return false;
}
}
return true;
}
I would like to replace ??? MAGIC ??? with a LINQ expression to see if item is "equal" to an element in right using the passed in delegate func. Is this even possible?
Note: For reasons I don't want to bother getting into here, impelemnting IEquatable or overriding the Equals method is not an option here.
It looks like you want .All() and .Any() methods (first method checks that all elements satisfy condition second only check if such an element exist) :
bool leftItemIsInRightCollection = right.Any(rItem => func(item, rItem));
Also i'd refactor your code to something like :
private static bool HasSameCollectionItems<T>(ICollection<T> left, ICollection<T> right, Func<T, T, bool> func)
{
return left.Count == right.Count && left.All(LI => right.Any(RI => func(LI, RI)));
}
The following works by checking whether there are element in left which are not in right.
If you insist on a delegate to determine equality, you can use the FuncEqualityComparer from here. (Note that you must also provide an implementation for Object.GetHashCode)
private static bool HasSameCollectionItems<T>(ICollection<T> left, ICollection<T> right, IEqualityComparer<T> comparer)
{
if (left.Count != right.Count) return false;
return !left.Except(right, comparer).Any();
}
What is the difference between Contains and Any in LINQ?
Contains takes an object, Any takes a predicate.
You use Contains like this:
listOFInts.Contains(1);
and Any like this:
listOfInts.Any(i => i == 1);
listOfInts.Any(i => i % 2 == 0); // Check if any element is an Even Number
So if you want to check for a specific condition, use Any. If you want to check for the existence of an element, use Contains.
MSDN for Contains, Any
Contains checks if the sequence contains a specified element.
Enumerable.Any checks if element of a sequence satisfies a condition.
Consider the following example:
List<int> list = new List<int> { 1, 2, 3, 4, 5 };
bool contains = list.Contains(1); //true
bool condition = list.Any(r => r > 2 && r < 5);
Contains cares about whether the source collection is an ICollection, Any does not.
Enumerable.Contains
http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs#f60bab4c5e27a849
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value)
{
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null)
{
return collection.Contains(value);
}
return source.Contains<TSource>(value, null);
}
Enumerable.Any
http://referencesource.microsoft.com/#System.Core/System/Linq/Enumerable.cs#6a1af7c3d17845e3
public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
foreach (TSource local in source)
{
if (predicate(local))
{
return true;
}
}
return false;
}
Another difference as mentioned here is on the performance
Contains is O(n) for a List and O(1) for a HashSet
Any is simply O(n)
Contains
Determines whether a sequence contains a specified element by using the default equality comparer.
Any
Determines whether a sequence contains any elements.
As for the documentation:
Can't seem to find to find any documentation on it.
All (most?) LINQ extension methods: here
Say I have ISet<T> _set = new HashSet<T>();
Now if I do: _set.Cast<TInterface>().Contains(obj, comparer); (where T implements TInterface), do I loose the O(1) benefit of the HashSet<T>?
In other words - does .Cast<T>()ing changes the underlying type (HashSet<T> in this case) to something else, or the underlying type preserved?
Logically, a HashSet<T> uses an internal hash-table based on the hashing logic of the comparer that it was created with, so of course it's not possible to do an element-containment test on it with a different comparer and expect O(1) performance.
That said, let's look at things in a bit more detail for your specific scenario:
The Cast<T> method looks like this (from reference-source):
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) {
IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
if (typedSource != null) return typedSource;
if (source == null) throw Error.ArgumentNull("source");
return CastIterator<TResult>(source);
}
As you can see, if the source implements IEnumerable<TResult> it just returns the source directly. Since IEnumerable<> is a covariant interface, this test will pass for your use case (assuming the concrete type implements the interface type) and the hash-set will be returned directly - a good thing as there's still hope of its internal hash-table being used.
However, the overload of Contains you are using looks like this:
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
{
if (comparer == null) comparer = EqualityComparer<TSource>.Default;
if (source == null) throw Error.ArgumentNull("source");
foreach (TSource element in source)
if (comparer.Equals(element, value)) return true;
return false;
}
As you can see, it always loops through the collection to linear-search, which is O(n).
So the entire operation is going to be O(n) regardless.
_set.Cast<TInterface>() will return an IEnumerable<TInterface> so _set.Cast<TInterface>().Contains(obj, comparer); doesn't invokes HashSet.Contains, rather it invokes Enumerable.Contains extension method.
So obviously you don't get O(1) operation anymore.
If you need O(1) you again need to create a HashSet out of it.
var newSet = new HashSet(_set.Cast<TInterface>(),comparer);
newSet.Contains();
The Cast method returns an IEnumerable so the Contains method will operate on the IEnumerable rather than the HashSet. So I think you'd loose the benefit of HashSet. Why don't you do the cast in the compared instead?
So I know that Find() is only a List<T> method, whereas First() is an extension for any IEnumerable<T>. I also know that First() will return the first element if no parameter is passed, whereas Find() will throw an exception. Lastly, I know that First() will throw an exception if the element is not found, whereas Find() will return the type's default value.
I hope that clears up confusion about what I'm actually asking. This is a computer science question and deals with these methods at the computational level. I've come to understand that IEnumerable<T> extensions do not always operate as one would expect under the hood. So here's the Q, and I mean from a "close to the metal" standpoint: What is the difference between Find() and First()?
Here's some code to provide basic assumptions to operate under for this question.
var l = new List<int> { 1, 2, 3, 4, 5 };
var x = l.First(i => i == 3);
var y = l.Find(i => i == 3);
Is there any actual computational difference between how First() and Find() discover their values in the code above?
Note: Let us ignore things like AsParallel() and AsQueryable() for now.
Here's the code for List<T>.Find (from Reflector):
public T Find(Predicate<T> match)
{
if (match == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
}
for (int i = 0; i < this._size; i++)
{
if (match(this._items[i]))
{
return this._items[i];
}
}
return default(T);
}
And here's Enumerable.First:
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
if (predicate == null)
{
throw Error.ArgumentNull("predicate");
}
foreach (TSource local in source)
{
if (predicate(local))
{
return local;
}
}
throw Error.NoMatch();
}
So both methods work roughly the same way: they iterate all items until they find one that matches the predicate. The only noticeable difference is that Find uses a for loop because it already knows the number of elements, and First uses a foreach loop because it doesn't know it.
First will throw an exception when it finds nothing, FirstOrDefault however does exactly the same as Find (apart from how it iterates through the elements).
BTW Find is rather equal to FirstOrDefault() than to First(). Because if predicate of First() is not satisfied with any list elements you will get an exception.
Here what returns a dotpeek, another great free reflector replacement with some of ReSharper features
Here for Enumerable.First(...) and Enumerable.FirstOrDefault(...) extension methods:
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
foreach (TSource element in source) {
if (predicate(element)) return element;
}
return default(TSource);
}
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
foreach (TSource element in source) {
if (predicate(element)) return element;
}
throw Error.NoMatch();
}
and here is for List<>.Find:
/// <summary>
/// Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire <see cref="T:System.Collections.Generic.List`1"/>.
/// </summary>
///
/// <returns>
/// The first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type <paramref name="T"/>.
/// </returns>
/// <param name="match">The <see cref="T:System.Predicate`1"/> delegate that defines the conditions of the element to search for.</param><exception cref="T:System.ArgumentNullException"><paramref name="match"/> is null.</exception>
[__DynamicallyInvokable]
public T Find(Predicate<T> match)
{
if (match == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
for (int index = 0; index < this._size; ++index)
{
if (match(this._items[index]))
return this._items[index];
}
return default (T);
}
1- Find() returns Null if the entity is not in the context but First() will throw an exception
2- Find() returns entities that have been added to the context but have not yet been saved to the database
Since List<> is not indexed in any way, it has to go through all values to find a specific value. Therefore it doesn't make much of a difference compared to traversing the list via an enumerable (apart from the creation of a enumerable helper object instance).
That said, keep in mind that the Find function was created way earlier than the First extension method (Framework V2.0 vs. V3.5), and I doubt that they would have implemented Find if the List<> class had been implemented at the same time as the extension methods.