Trying to append objects to an Enumerable in a foreach loop - c#

I'm doing a C# exercise to create an operation that takes a collection, performs a function on each object in the collection, and returns a collection of modified objects.
My code is currently as follows:
public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
{
IEnumerable<U> output = Enumerable.Empty<U>();
foreach (T item in collection)
{
output.Append(func(item));
}
return output;
}
This is only returning an empty collection, and I have no idea why.
I have tried creating a copy of the item in the foreach after seeing this approach in another thread, like so:
foreach (T item in collection)
{
U copy = func(item);
output.Append(copy);
}
but that didn't solve anything.
I did some research but couldn't really find any examples doing exactly what I'm trying to do here. I read some things about closure, but couldn't really understand it, as I'm new to C#.

To answer your actual question: The reason it isn't working is because
output.Append(func(item));
doesn't change output - instead, it returns a new sequence which is func(item) appended to output. Thus when you eventually return output you are just returning the original, empty sequence.
You could make yours work by this simple change:
output = output.Append(func(item));
However, this is not an efficient approach - you're much better off using yield, by modifying your method as follows:
public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
{
foreach (T item in collection)
{
yield return func(item);
}
}
Although note that that is more simply expressed as:
public static IEnumerable<U> Accumulate<T, U>(this IEnumerable<T> collection, Func<T, U> func)
{
return collection.Select(item => func(item));
}
But it is useful to know about how to do this with yield so that you can write solutions to more complex Linq-like problems.

Usually, when I want to achieve this kind of behaviour, I make use of C# Iterators.
They are so usefull when you want to process an iteration on some kind of data and, at each iteration, return a value that is appended to your resulting collection.
Take a look at the docs: MS Docs

Related

Update IEnumerable with new object in extension method

I would like to add new iEnumerable object to original one. Can I do this updating original object in extenstion method like following?
public static void AddItems<TSource>(this IEnumerable<TSource> orginalColl,
IEnumerable<TSource> collectionToAdd)
{
foreach (var item in collectionToAdd)
{
orginalColl.ToList<TSource>().Add(item);
}
}
I am calling like this: OrgCollecation.AddItems(newCollection).
But this does not seems to work. Any idea?
An IEnumerable[<T>] is not intended for adding. You can concatenate (generating a new sequence), but that doesn't change the original sequence (/list/array/etc). You can do that with Enumerable.Concat, i.e. return orginalColl.Concat(...). But emphasis: this does not update the original collection.
What you could do would be to cast to IList[<T>] or similar, but that would be abusive (and will only work for some scenarios, not all). It won't work, for example, for anything that is based on an iterator block (or any other IEnumerable<T> that is not also an IList<T>) - for example it won't work on someSource.Where(predicte).
If you expect to change the source, then you should be passing in something like IList[<T>]. For example:
public static void AddItems<TSource>(this IList<TSource> orginalColl,
IEnumerable<TSource> collectionToAdd)
{
foreach (var item in collectionToAdd)
{
orginalColl.Add(item);
}
}
(btw, AddRange would be an alternative name for the above, to match List<T>.AddRange)
No you can not.
In your code you are cloning the source enumerable into list, then adding elements to it and forgetting, because you are not returning anything.
Try
var result = orginalColl.Concat(collectionToAdd);
Take a look at http://msdn.microsoft.com/en-us/library/bb302894.aspx for more information and examples.
In short, an IEnumerable<T> should be considered immutable, and you can't add to it. You don't know what kind of collection is implementing it, it may for example be a serial port input or a read only file in the file system you're enumerating from.
What you're trying to do to the collection matches the use case of ICollection<T> better; it's implemented by generic (mutable) collections in the framework.
public static void AddItems<TSource>(this ICollection<TSource> orginalColl,
IEnumerable<TSource> collectionToAdd)
{
foreach (var item in collectionToAdd)
{
orginalColl.Add(item);
}
}

ICollection<T> is non-index based, but TakeWhile() exists

I'm trying to replace usages of T[] or List<T> as function parameters and return values with more appropriate types such as IEnumerable<T>, ICollection<T> and IList<T>.
ICollection<T> from my understanding is preferrable to IList<T> where you are only needing basic/simple collection functionality (eg an enumerator and count functionality) as it provides this with the least restriction. From reading on here one of the main differentiators I thought was that ICollection<T> doesn't require that the underlying collection to be index based where IList<T> does?
In switching my List<T> references over I needed to replace a List<T>.GetRange() call and I was very surprised to find the ICollection<T>.TakeWhile() extension method which has an overload supporting selection based on index?! (msdn link)
I'm confused why this method exists on ICollection where there is nothing index based on this interface? Have I misunderstood or how can this method actually work if the underlying collection is eg a Hashset or something?
The method, like most of LINQ, is on IEnumerable<T>. Any features that just pass the indexer to the consumer (such as TakeWhile) only need to loop while incrementing a counter. Some APIs may be able to optimize using an indexer, and then it is up to them to decide whether to do that, or just use IEnumerable<T> and simply skip (etc) unwanted data.
For example:
int i = 0;
foreach(var item in source) {
if(!predicate(i++, item)) break;
yield return item;
}
Indexing can be done without collection's support of it
int i = -1;
foreach(var item in collection)
{
i++;
// item is at index i;
}
TakeWhile and other extension methods from System.Linq.Enumerable class work on all the types implementing IEnumerable<T>. They all iterate over the collection (using foreach statement) and perform appropriate actions.
Here is the implementation of the TakeWhile method, with some simplifications:
private static IEnumerable<TSource> TakeWhile<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
foreach (TSource item in source)
{
if (!predicate(item))
{
break;
}
yield return item;
}
}
As you see, it simply iterates over the collection, and evaluates the predicate. This is true for almost all other LINQ methods. The same will happen when you use any other collection, like HashSet<T>.

How to create an extension method to handle bindinglist.removeall with predicate input

myGenericList.RemoveAll(x => (x.StudentName == "bad student"));
Works great, but a bindinglist does not have this method. How can I create an extension method for the bindinglist that takes as input a predicate and does the magic like the canned removeall for List
thankyou
Like I said in a comment, there is no magic in extension methods, just write the code the same way as if you wrote it normally, just put it in a static method in a static class and use the this keyword:
public static void RemoveAll<T>(this BindingList<T> list, Func<T, bool> predicate)
{
foreach (var item in list.Where(predicate).ToArray())
list.Remove(item);
}
You have to use ToArray() (or ToList()), because Where() is lazy and only enumerates the collection when needed and you can't enumerate changing collection.
Although this solution is quite slow (O(N2)), because every Remove() has to look through the collection to find the correct item to remove. We can do better:
public static void FastRemoveAll<T>(this BindingList<T> list, Func<T, bool> predicate)
{
for (int i = list.Count - 1; i >= 0; i--)
if (predicate(list[i]))
list.RemoveAt(i);
}
This uses the fact that we can get to i-th item in constant time, so the whole method is O(N). The iteration is easier to write backwards, so that indexes of items we have yet to consider aren't changing.
EDIT: Actually the second solution is still O(N2), because every RemoveAt() has to move all the items after the one that was removed.
I'd say:
public static class BindingListExtensions
{
public static void RemoveAll<T>(this BindingList<T> list, Func<T, bool> predicate)
{
// first check predicates -- uses System.Linq
// could collapse into the foreach, but still must use
// ToList() or ToArray() to avoid deferred execution
var toRemove = list.Where(predicate).ToList();
// then loop and remove after
foreach (var item in toRemove)
{
list.Remove(item);
}
}
}
And for those interested in the minutia, seems ToList() and ToArray() are so close to the same performance (and in fact each can be faster based on the circumstance) as to be negligible: I need to iterate and count. What is fastest or preferred: ToArray() or ToList()?

Is there a neater linq way to 'Union' a single item?

If I have two sequences and I want to process them both together, I can union them and away we go.
Now lets say I have a single item I want to process between the two sequencs. I can get it in by creating an array with a single item, but is there a neater way? i.e.
var top = new string[] { "Crusty bread", "Mayonnaise" };
string filling = "BTL";
var bottom = new string[] { "Mayonnaise", "Crusty bread" };
// Will not compile, filling is a string, therefore is not Enumerable
//var sandwich = top.Union(filling).Union(bottom);
// Compiles and works, but feels grungy (looks like it might be smelly)
var sandwich = top.Union(new string[]{filling}).Union(bottom);
foreach (var item in sandwich)
Process(item);
Is there an approved way of doing this, or is this the approved way?
Thanks
One option is to overload it yourself:
public static IEnumerable<T> Union<T>(this IEnumerable<T> source, T item)
{
return source.Union(Enumerable.Repeat(item, 1));
}
That's what we did with Concat in MoreLINQ.
The new way of doing this, supported in .NET Core and .NET Framework from version 4.7.1, is using the Append extension method.
This will make your code as easy and elegant as
var sandwich = top.Append(filling).Union(bottom);
Consider using even more flexible approach:
public static IEnumerable<T> Union<T>(this IEnumerable<T> source, params T[] items)
{
return source.Union((IEnumerable<T>)items);
}
Works for single as well as multiple items.
You may also accept null source values:
public static IEnumerable<T> Union<T>(this IEnumerable<T> source, params T[] items)
{
return source != null ? source.Union((IEnumerable<T>)items) : items;
}
I tend to have the following somewhere in my code:
public static IEnumerable<T> EmitFromEnum<T>(this T item)
{
yield return item;
}
While it's not as neat to call col.Union(obj.EmitFromEnum()); as col.Union(obj) it does mean that this single extension method covers all other cases I might want such a single-item enumeration.
Update: With .NET Core you can now use .Append() or .Prepend() to add a single element to an enumerable. The implementation is optimised to avoid generating too many IEnumerator implementations behind the scenes.

How do I implement a matching algorithm using predicates?

I understand how to use delegates and I am okay with lambda expressions to make use of predicates. I've come to a point where I want to implement a method that uses a predicate as an argument and can't figure out how to reference the predicate to find the matches in my collection:
private static T FindInCollection<T>(ICollection<T> collection, Predicate<T> match)
{
foreach (T item in collection)
{
//So how do I reference match to return the matching item?
}
return default(T);
}
I want to then reference this using something akin to:
ICollection<MyTestClass> receivedList = //Some list I've received from somewhere else
MyTestClass UsefulItem = FindInCollection<MyTestClass>(receivedList, i => i.SomeField = "TheMatchingData");
If anyone can give me an explanation or point me to a reference regarding implementation of predicates, I'd appreciate it. The documentation out there seems to all relate to passing predicates (which I can do just fine), not actually implementing the functionality that uses them...
Thanks
private static T FindInCollection<T>(ICollection<T> collection, Predicate<T> match)
{
foreach (T item in collection)
{
if (match(item))
return item;
}
return default(T);
}
You just use the predicate like any other delegate. It's basically a method you can call with any argument of type T, which will return true.

Categories