Create Extension Method of ICollection<T> after .Count() - c#

Im trying to create a very simple extension method that returns true or false if the count of any Collection is equals to one. I have the corresponding Method. But that method runs the .Count() inside of it. The idea is to run only the validation after the count, for example: myList.Count().EqualsToOne();
I dont know if it have something to do with receiving a func an invoke it (tho it would be the same I think).
This is the implementation:
public static class ExtensionMethods
{
public static bool EqualsToOne<T>(this ICollection<T> sequence)
{
int count = sequence.Count();
if(count == 1)
{
return true;
}
return false;
}
}
static void Main(string[] args)
{
Employee emp = new Employee() { Id = 1 };
List<Employee> lstEmployee = new List<Employee>()
{
emp,
};
//The idea should be lstEmployee.Count().EqualsToOne()
bool result = lstEmployee.EqualsToOne();
Console.WriteLine(result.ToString());
Console.ReadLine();
lstEmployee.Add(emp);
result = lstEmployee.EqualsToOne();
Console.WriteLine(result.ToString());
Console.ReadLine();
}

I don't know why you would want this. But here it is: Count() returns an int, and that int is what you want to extend:
public static bool EqualsToOne(this int i) => i == 1;
But in fact, if this is only about instance of ICollection<T>, this interface already provides a property Count. There is no need to use linq's Count() extension. Simply collection.Count == 1 is all you need.
If you want to extend this to other IEnumerable<T> instances, I would avoid Count()ing the whole sequence if you just want to know it's exactly one element.
So I'd change your first implementation to this:
public static bool SequenceHasExactlyOneElement<T>(this IEnumerable<T> source)
{
if (source == null) throw new ArgumentNullException(nameof(source));
using(var enumerator = source.GetEnumerator())
return enumerator.MoveNext() && !enumerator.MoveNext();
}

Related

How to create an Extension method for a list to return null if list is empty or return full list

I have multiple lists of different objects.
for all objects I want to return null if it's an empty list or return full list.
How can i achieve that?
I want to do something like
address = person.addresses.tolist().count > 0 ? person.addresses.tolist : null;
aliases = person.aliases.tolist().count > 0 ? person.aliases.toList() : null;
trackingCodes = person.trackingCodes .tolist().count > 0 ? person.trackingCodes .toList() : null;
In the above line of code, i am computing addresses list twice.
I was wondering if i could create an extension method that can be uses as
address = patient.addresses.tolist().GetListOrNull()
and the GetListOrNull() method returns either list or null value.
Is this possible?
Extension methods have to be in a static class and have to be static.
You could write something like:
public static class EnumerableExtensions
{
public static IList<T> GetListOrNull<T>(this IEnumerable<T> items)
{
if (items == null)
{
return null;
}
// optimization to avoid creating a new list when the input already implements `IList`
if (!(items is IList<T> tmp))
{
tmp = items.ToList();
}
return tmp.Any() ? tmp : null;
}
// or a list-specific version
public static IList<T> GetListOrNull<T>(this IList<T> items)
{
if (items == null)
{
return null;
}
return items.Any() ? items : null;
}
}
Here is a version that works on IEnumerable so that it can be a little more generic.
I think .Any() is a little more succinct than .Count > 0
public static class MyExtentions
{
public static IEnumerable<T> ToNullIfEmpty<T>(this IEnumerable<T> container)
{
if(container == null || !container.Any())
return null;
else
return container;
}
}

Creating an IEnumerable<> from a generator method using a factory function

I have a factory function, and want to use it to create an Enumerable. In C# I didn't find a straight-forward declarative way to do the job. So I did it like this:
public IEnumerable<Contact> Get()
{
return Enumerable.Range(1, 5).Select(x => GenerateRandomContact());
}
Is there any better way?
// Expected format
public IEnumerable<Contact> Get()
{
return Enumerable.Generate(GenerateRandomContact).Take(5);
}
Something like:
public static IEnumerable<T> Generate(Func<T> generator)
{
while(true)
yield return generator.Invoke();
}
But you can't extend static classes. So you should place it in a helper class.
public IEnumerable<Contact> Get()
{
for(int i = 1; i <= 5; i ++)
{
yield return GenerateRandomContact();
}
}
or if you want a specific amount you can do this
public IEnumerable<Contact> Get(int number)
{
for(var i = 1; i <= number; i ++) //is the same as for (var i = 1;; i++) you got the idea
{
yield return GenerateRandomContact();
}
}
You are expecting something like Enumerable.Generate()
In order to get a list of elements that you want to Enumerate, your Generate method should return an Enumerable Value. You are trying to create an extension method for Enumerable based on your approach. Before that try to see the implementation of Range
public static IEnumerable<int> Range(int start, int count)
{
long max = ((long)start) + count - 1;
if (count < 0 || max > Int32.MaxValue) throw Error.ArgumentOutOfRange("count");
return RangeIterator(start, count);
}
static IEnumerable<int> RangeIterator(int start, int count)
{
for (int i = 0; i < count; i++) yield return start + i;
}
In that case with the yield, .NET creates the IEnumerable class for you and based on a specific amount. Maybe you should consider passing the amount on the Generate method, or like the other extensions as Concat, you should pass the IEnumerable, see bellow how they pass to the Contact mehotd the IEnumerable first variable
public static IEnumerable<TSource> Concat<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
{
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return ConcatIterator<TSource>(first, second);
}
With that said.
You can use my first approach or your GenerateRandomContact should return an IEnumerable of Contact, but there is the problem, how much elements you want on that Random creation, or you don't specify the amount as bellow
public IEnumerable<Contact> GenerateRandomContact()
{
var random = new Random(Environment.TickCount);
for (int i = 0; i < 100; i++)
{
yield return new Contact
{
Name = $"Name_{random.Next()}"
};
}
}
or you pass the parameter
But the whole problem now is, if you want to call your method as Enumerable.Generate, that is not possible, You can't have extension methods on static classes because extension methods are only applicable to instantiable types and static classes cannot be instantiated.
Your call should be
IEnumerable<Contact> contacts = new List<Contact>(){....}
//where contacts is an instance of type
contacts.Generate
even in the case you want this syntax
contacts.Generate(GenerateRandomContact).Take(5);
your extension method should accept a function but here I am relying on the previous GenerateRandomContact() where I put 100 random contacts
public static class Extension
{
public static IEnumerable<T> Generate<T>(this IEnumerable<T> elements, Func<IEnumerable<T>> func)
{
if (func != null)
{
return func();
}
return Enumerable.Empty<T>();
}
}
IMHO try to consider passing the amount that you want to take. Your syntax will change a little bit
class Program
{
static void Main(string[] args)
{
IEnumerable<Contact> contacts = new List<Contact>()
{
new Contact
{
Name = "Name1"
},
new Contact
{
Name = "Name2"
}
}; //load your methods from the database or create them here
var res = contacts.Generate(GenerateRandomContact, 5);
Console.ReadLine();
}
static IEnumerable<Contact> GenerateRandomContact(int amount)
{
var random = new Random(Environment.TickCount);
for (int i = 0; i < amount; i++)
{
yield return new Contact
{
Name = $"Name_{random.Next()}"
};
}
}
}
public class Contact
{
public string Name { get; set; }
}
public static class Extension
{
public static IEnumerable<T> Generate<T>(this IEnumerable<T> elements, Func<int, IEnumerable<T>> func, int amount)
{
if (func != null)
{
return func(amount);
}
return Enumerable.Empty<T>();
}
}
}

check if record is last or first in list with linq

I have a list of objects.
I want to determine when the user will get the first or last object in the list, that way I can disable some buttons on the page.
For example I might have some boolean and if the object requested is last or first in the list, then it will return true, otherwise false.
Any idea?
If your list of objects is indeed a List, it might be better to use it explicitly (adapted the Mehmet Ataş's answer):
static class ListExtensions
{
public static bool IsFirst<T>(this List<T> items, T item)
{
if (items.Count == 0)
return false;
T first = items[0];
return item.Equals(first);
}
public static bool IsLast<T>(this List<T> items, T item)
{
if (items.Count == 0)
return false;
T last = items[items.Count-1];
return item.Equals(last);
}
}
This way you eliminate the LINQ overhead (it's not much, but it's significant). However, your code must use List<T> for this to work.
You can wrtie an extension method such as
public static class IEnumerableExtensions
{
public static bool IsLast<T>(this IEnumerable<T> items, T item)
{
var last = items.LastOrDefault();
if (last == null)
return false;
return item.Equals(last); // OR Object.ReferenceEquals(last, item)
}
public static bool IsFirst<T>(this IEnumerable<T> items, T item)
{
var first = items.FirstOrDefault();
if (first == null)
return false;
return item.Equals(first);
}
public static bool IsFirstOrLast<T>(this IEnumerable<T> items, T item)
{
return items.IsFirst(item) || items.IsLast(item);
}
}
You can use it like
IEnumerable<User> users = // something
User user = // something
bool isFirstOrLast = users.IsFirstOrLast(user);
var yourObject = yourList[0];
if(list.Count > 0)
if(yourObject == list.First() || yourobject == list.Last())
{
//item is either first or last
}
But remember to check if the list contains atleast 1 item, otherwise you will end up with exception from First, Last.
The above will compare the reference for the objects, you can compare their values by implementing a custom IComparable or you may compare their values.

What's the point of Enumerable.ElementAt<TSource>?

IEnumerable<T> exposes an enumerator, so the object can be enumerated. There is nothing about indexes exposed by this interface. IList<T> is about indexes, as it exposes the IndexOf method.
So what's the point of Enumerable.ElementAt? I just read the doc of this LINQ extension method:
Returns the element at a specified index in a sequence.
Well, yes, it's about a sequence, not just an IEnumerable. Reading the remarks:
If the type of source implements IList, that implementation is used
to obtain the element at the specified index. Otherwise, this method
obtains the specified element.
Okay, so if the concrete type implements something that inherits from IList<T> (which is an actual sequence), then it's the same as IndexOf(). If not, it iterates until the index is reached.
Here's a sample scenario:
// Some extension method exposed by a lib
// I know it's not a good piece of code, but let's say it's coded this way:
public static class EnumerableExtensions
{
// Returns true if all elements are ordered
public static bool IsEnumerableOrdered(this IEnumerable<int> value)
{
// Iterates over elements using an index
for (int i = 0; i < value.Count() - 1; i++)
{
if (value.ElementAt(i) > value.ElementAt(i + 1))
{
return false;
}
}
return true;
}
}
// Here's a collection that is enumerable, but doesn't always returns
// its objects in the same order
public class RandomAccessEnumerable<T> : IEnumerable<T>
{
private List<T> innerList;
private static Random rnd = new Random();
public RandomAccessEnumerable(IEnumerable<T> list)
{
innerList = list.ToList();
}
public IEnumerator<T> GetEnumerator()
{
var listCount = this.innerList.Count;
List<int> enumeratedIndexes = new List<int>();
for (int i = 0; i < listCount; i++)
{
int randomIndex = -1;
while (randomIndex < 0 || enumeratedIndexes.Contains(randomIndex))
{
randomIndex = rnd.Next(listCount);
}
enumeratedIndexes.Add(randomIndex);
yield return this.innerList[randomIndex];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
// Here's some test program
internal class Program
{
private static void Main()
{
var test0 = new List<int> { 0, 1, 2, 3 };
var test1 = new RandomAccessEnumerable<int>(test0);
Console.WriteLine("With List");
Console.WriteLine(test0.IsEnumerableOrdered()); // true
Console.WriteLine(test0.IsEnumerableOrdered()); // true
Console.WriteLine(test0.IsEnumerableOrdered()); // true
Console.WriteLine(test0.IsEnumerableOrdered()); // true
Console.WriteLine(test0.IsEnumerableOrdered()); // true
Console.WriteLine("With RandomAccessEnumerable");
Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
Console.WriteLine(test1.IsEnumerableOrdered()); // might be true or false
Console.Read();
}
}
So, as RandomAccessEnumerable might return enumerated objects in a random order, you just can't rely on the simple IEnumerable<T> interface to assume your elements are indexed. So you don't want to use ElementAt for an IEnumerable.
In the above example, I think IsEnumerableOrdered should require a IList<T> parameter as it implies elements are a sequence. I actually can't find a scenario where the ElementAt method is useful, and not bug-prone.
There are many IEnumerable types like array or list. All IList types(which Array also implements) have an indexer which you can use to access elements at a specific index.
This will be used by Enumerable.ElementAt if the sequence can be casted to IList successfully. Otherwise it will be enumerated.
So it's just a convenient way to access elements at a given index for all kind of IEnumerable types.
This has the advantage that you can change the type later without needing to change all occurences of arr[index].
For what it's worth, here's the reflected(ILSpy) method to demonstrate what i've said:
public static TSource ElementAt<TSource>(this IEnumerable<TSource> source, int index)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
return list[index];
}
if (index < 0)
{
throw Error.ArgumentOutOfRange("index");
}
TSource current;
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
while (enumerator.MoveNext())
{
if (index == 0)
{
current = enumerator.Current;
return current;
}
index--;
}
throw Error.ArgumentOutOfRange("index");
}
return current;
}

How to get the index of an element in an IEnumerable?

I wrote this:
public static class EnumerableExtensions
{
public static int IndexOf<T>(this IEnumerable<T> obj, T value)
{
return obj
.Select((a, i) => (a.Equals(value)) ? i : -1)
.Max();
}
public static int IndexOf<T>(this IEnumerable<T> obj, T value
, IEqualityComparer<T> comparer)
{
return obj
.Select((a, i) => (comparer.Equals(a, value)) ? i : -1)
.Max();
}
}
But I don't know if it already exists, does it?
I'd question the wisdom, but perhaps:
source.TakeWhile(x => x != value).Count();
(using EqualityComparer<T>.Default to emulate != if needed) - but you need to watch to return -1 if not found... so perhaps just do it the long way
public static int IndexOf<T>(this IEnumerable<T> source, T value)
{
int index = 0;
var comparer = EqualityComparer<T>.Default; // or pass in as a parameter
foreach (T item in source)
{
if (comparer.Equals(item, value)) return index;
index++;
}
return -1;
}
The whole point of getting things out as IEnumerable is so you can lazily iterate over the contents. As such, there isn't really a concept of an index. What you are doing really doesn't make a lot of sense for an IEnumerable. If you need something that supports access by index, put it in an actual list or collection.
I would implement it like this:
public static class EnumerableExtensions
{
public static int IndexOf<T>(this IEnumerable<T> obj, T value)
{
return obj.IndexOf(value, null);
}
public static int IndexOf<T>(this IEnumerable<T> obj, T value, IEqualityComparer<T> comparer)
{
comparer = comparer ?? EqualityComparer<T>.Default;
var found = obj
.Select((a, i) => new { a, i })
.FirstOrDefault(x => comparer.Equals(x.a, value));
return found == null ? -1 : found.i;
}
}
The way I'm currently doing this is a bit shorter than those already suggested and as far as I can tell gives the desired result:
var index = haystack.ToList().IndexOf(needle);
It's a bit clunky, but it does the job and is fairly concise.
I think the best option is to implement like this:
public static int IndexOf<T>(this IEnumerable<T> enumerable, T element, IEqualityComparer<T> comparer = null)
{
int i = 0;
comparer = comparer ?? EqualityComparer<T>.Default;
foreach (var currentElement in enumerable)
{
if (comparer.Equals(currentElement, element))
{
return i;
}
i++;
}
return -1;
}
It will also not create the anonymous object
The best way to catch the position is by FindIndex This function is available only for List<>
Example
int id = listMyObject.FindIndex(x => x.Id == 15);
If you have enumerator or array use this way
int id = myEnumerator.ToList().FindIndex(x => x.Id == 15);
or
int id = myArray.ToList().FindIndex(x => x.Id == 15);
A bit late in the game, i know... but this is what i recently did. It is slightly different than yours, but allows the programmer to dictate what the equality operation needs to be (predicate). Which i find very useful when dealing with different types, since i then have a generic way of doing it regardless of object type and <T> built in equality operator.
It also has a very very small memory footprint, and is very, very fast/efficient... if you care about that.
At worse, you'll just add this to your list of extensions.
Anyway... here it is.
public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
int retval = -1;
var enumerator = source.GetEnumerator();
while (enumerator.MoveNext())
{
retval += 1;
if (predicate(enumerator.Current))
{
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
return retval;
}
}
IDisposable disposable = enumerator as System.IDisposable;
if (disposable != null) disposable.Dispose();
return -1;
}
Hopefully this helps someone.
A few years later, but this uses Linq, returns -1 if not found, doesn't create extra objects, and should short-circuit when found [as opposed to iterating over the entire IEnumerable]:
public static int IndexOf<T>(this IEnumerable<T> list, T item)
{
return list.Select((x, index) => EqualityComparer<T>.Default.Equals(item, x)
? index
: -1)
.FirstOr(x => x != -1, -1);
}
Where 'FirstOr' is:
public static T FirstOr<T>(this IEnumerable<T> source, T alternate)
{
return source.DefaultIfEmpty(alternate)
.First();
}
public static T FirstOr<T>(this IEnumerable<T> source, Func<T, bool> predicate, T alternate)
{
return source.Where(predicate)
.FirstOr(alternate);
}
Stumbled across this today in a search for answers and I thought I'd add my version to the list (No pun intended). It utlises the null conditional operator of c#6.0
IEnumerable<Item> collection = GetTheCollection();
var index = collection
.Select((item,idx) => new { Item = item, Index = idx })
//or .FirstOrDefault(_ => _.Item.Prop == something)
.FirstOrDefault(_ => _.Item == itemToFind)?.Index ?? -1;
I've done some 'racing of the old horses' (testing) and for large collections (~100,000), worst case scenario that item you want is at the end, this is 2x faster than doing ToList().FindIndex(). If the Item you want is in the middle its ~4x faster.
For smaller collections (~10,000) it seems to be only marginally faster
Heres how I tested it https://gist.github.com/insulind/16310945247fcf13ba186a45734f254e
An alternative to finding the index after the fact is to wrap the Enumerable, somewhat similar to using the Linq GroupBy() method.
public static class IndexedEnumerable
{
public static IndexedEnumerable<T> ToIndexed<T>(this IEnumerable<T> items)
{
return IndexedEnumerable<T>.Create(items);
}
}
public class IndexedEnumerable<T> : IEnumerable<IndexedEnumerable<T>.IndexedItem>
{
private readonly IEnumerable<IndexedItem> _items;
public IndexedEnumerable(IEnumerable<IndexedItem> items)
{
_items = items;
}
public class IndexedItem
{
public IndexedItem(int index, T value)
{
Index = index;
Value = value;
}
public T Value { get; private set; }
public int Index { get; private set; }
}
public static IndexedEnumerable<T> Create(IEnumerable<T> items)
{
return new IndexedEnumerable<T>(items.Select((item, index) => new IndexedItem(index, item)));
}
public IEnumerator<IndexedItem> GetEnumerator()
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Which gives a use case of:
var items = new[] {1, 2, 3};
var indexedItems = items.ToIndexed();
foreach (var item in indexedItems)
{
Console.WriteLine("items[{0}] = {1}", item.Index, item.Value);
}
This can get really cool with an extension (functioning as a proxy), for example:
collection.SelectWithIndex();
// vs.
collection.Select((item, index) => item);
Which will automagically assign indexes to the collection accessible via this Index property.
Interface:
public interface IIndexable
{
int Index { get; set; }
}
Custom extension (probably most useful for working with EF and DbContext):
public static class EnumerableXtensions
{
public static IEnumerable<TModel> SelectWithIndex<TModel>(
this IEnumerable<TModel> collection) where TModel : class, IIndexable
{
return collection.Select((item, index) =>
{
item.Index = index;
return item;
});
}
}
public class SomeModelDTO : IIndexable
{
public Guid Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int Index { get; set; }
}
// In a method
var items = from a in db.SomeTable
where a.Id == someValue
select new SomeModelDTO
{
Id = a.Id,
Name = a.Name,
Price = a.Price
};
return items.SelectWithIndex()
.OrderBy(m => m.Name)
.Skip(pageStart)
.Take(pageSize)
.ToList();
Try this:
static int FindIndex<T>(this IEnumerable<T> a, Predicate<T> f) =>
a.TakeWhile(x => !f(x)).Count();
static int IndexOf<T>(this IEnumerable<T> a, T value) =>
a.FindIndex(x => EqualityComparer<T>.Default.Equals(x, value));
var i = new[] { 1, 2, 3 }.IndexOf(2); // 1

Categories