Extension Method for List to compute WhereNot - c#

I have one requirement to implement the extension method for List to find out the WhereNot. I am not suppose to use any existing Linq extension method like where etc.
For Example
IEnumerable<int> list = new List<int> {1,2,3,4,5,6};
var whereNotListInt = list.WhereNot((num) => num > 3));
foreach(int i in whereNotListInt)
{
Console.WriteLine(i);
}
Output:-
1
2
3
IEnumerable<string> list = new List<string> {"Cat", "Dog"};
var whereNotListStr = list.WhereNot((str) => str.StartsWith("D")));
foreach(string str in whereNotListStr )
{
Console.WriteLine(str);
}
Output: Cat
I tried below solution, but not able to figure out how to call the function.
public static class Utility
{
public static IEnumerable<T> WhereNot<T>(this IEnumerable<T> list, Func<T, bool> func)
{
foreach (var item in list)
{
yield return func(item);
}
}
}

Since you only want to return items for which the condition is not true, only return each item when func() returns false on that item.
public static class Utility
{
public static IEnumerable<T> WhereNot<T>(this IEnumerable<T> list, Func<T, bool> func)
{
foreach (var item in list)
{
if (!func(item))
yield return item;
}
}
}

Related

Multiple IEnumerable iterations [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I want to pass IEnumerable while having IEnumerable of IEnumerable.
Use case
class A
{
IEnumerable<int> _ints;
public A(IEnumerable<int> ints) => _ints = ints;
public B CreateB() => new B(_ints);
}
class B
{
public B(IEnumerable<int> ints)
{
foreach (int i in ints) { Console.WriteLine(i); }
}
}
class Program {
static void Main() {
var a = new A();
a.CreateB(); // Sequence 1
a.CreateB(); // Sequence 2
}
}
There are 2 solutions.
1: Special IEnumerable which returns different sequence from GetEnumerator.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
internal class MultiEnumerable<T> : IEnumerable<T>
{
private IEnumerable<IEnumerable<T>> _source;
public MultiEnumerable(IEnumerable<IEnumerable<T>> source)
{
_source = source;
}
public IEnumerator<T> GetEnumerator()
{
var current = _source.Take(1).First();
_source = _source.Skip(1);
return current.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public static class MultiEnumerableExtension
{
public static IEnumerable<T> AsMultiEnumerable<T>(this IEnumerable<IEnumerable<T>> source)
{
return new MultiEnumerable<T>(source);
}
}
static class Program
{
public static void Main()
{
IEnumerable<IEnumerable<int>> arrayOfArray =
new[]
{
new[] {1}, new[] {2}, new[] {3}, new[] {4}
};
IEnumerable<int> arrayOfArrayAsEnumerable = arrayOfArray.AsMultiEnumerable();
for (int x = 0; x < 4; x++)
{
Console.WriteLine("---");
foreach (var i in arrayOfArrayAsEnumerable)
{
Console.WriteLine(i);
}
}
}
}
}
Solution 2: Use method which takes IEnumerable of IEnumerable and returns first sequence while advancing:
class Utils{
public static IEnumerable<T> GetFirstAndAdvance<T>(ref IEnumerable<IEnumerable<T>> source)
{
var res = source.First();
source = source.Skip(1);
return res;
}
}
class A
{
IEnumerable<IEnumerable<int>> _ints;
public A(IEnumerable<IEnumerable<int>> ints) => _ints = ints;
public B CreateB() => new B(Utils.GetFirstAndAdvance(ref _ints));
}
There are a bunch of issues with your implementation of MultiEnumerable<T>.
To start with, these two lines are causing multiple iterations of the outer enumerable:
var current = _source.Take(1).First();
_source = _source.Skip(1);
Each time you go back and call GetEnumerator() you're running through the outer enumerable again to get back to the next inner enumerable.
Next, you're expecting the caller to know how many times to call GetEnumerator(). You've done this in your code with the for (int x = 0; x < 4; x++) where you know you should iterate the code 4 times. Had you iterated 5 times you would have gotten a n InvalidOperationException exception telling you that the "Sequence contains no elements".
These problems would have gone away had you written your test code using standard C# foreach loops.
foreach (var array in arrayOfArray)
{
Console.WriteLine("---");
foreach (var i in array)
{
Console.WriteLine(i);
}
}
Which really then leads to a way of writing a better MultiEnumerable<T>
internal class MultiEnumerable<T> : IEnumerable<T>
{
private IEnumerable<IEnumerable<T>> _source;
public MultiEnumerable(IEnumerable<IEnumerable<T>> source)
{
_source = source;
}
private IEnumerable<T> Iterate()
{
foreach (var inner in _source)
{
foreach (var element in inner)
{
yield return element;
}
}
}
public IEnumerator<T> GetEnumerator() => this.Iterate().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();
}
Or even more simply, ignore the helper class, and just implement like this:
public static IEnumerable<T> AsMultiEnumerable<T>(this IEnumerable<IEnumerable<T>> source)
{
foreach (var inner in source)
{
foreach (var element in inner)
{
yield return element;
}
}
}
Naturally, your test code becomes simpler in both implementations:
IEnumerable<int> arrayOfArrayAsEnumerable = arrayOfArray.AsMultiEnumerable();
foreach (var i in arrayOfArrayAsEnumerable)
{
Console.WriteLine(i);
}
However, this code now just re-implements SelectMany. You could have just written your code like this:
foreach (var i in arrayOfArray.SelectMany(x => x))
{
Console.WriteLine(i);
}
It's better to use a well-known, standard operator as the code should then be easier to read and reason about.
You can use LINQ's SelectMany method.
IEnumerable<IEnumerable<int>> arrayOfArray = new[]
{
new[] {1}, new[] {2}, new[] {3}, new[] {4}
};
var allElements = arrayOfArray.SelectMany(element => element);
foreach (var element in allElements)
{
Console.WriteLine(element);
}
// Output:
// 1
// 2
// 3
// 4

How to build a sequence using a fluent interface?

I'm trying to using a fluent interface to build a collection, similar to this (simplified) example:
var a = StartWith(1).Add(2).Add(3).Add(4).ToArray();
/* a = int[] {1,2,3,4}; */
The best solution I can come up with add Add() as:
IEnumerable<T> Add<T>(this IEnumerable<T> coll, T item)
{
foreach(var t in coll) yield return t;
yield return item;
}
Which seems to add a lot of overhead that going to be repeated in each call.
IS there a better way?
UPDATE:
in my rush, I over-simplified the example, and left out an important requirement. The last item in the existing coll influences the next item. So, a slightly less simplified example:
var a = StartWith(1).Times10Plus(2).Times10Plus(3).Times10Plus(4).ToArray();
/* a = int[] {1,12,123,1234}; */
public static IEnumerable<T> StartWith<T>(T x)
{
yield return x;
}
static public IEnumerable<int> Times10Plus(this IEnumerable<int> coll, int item)
{
int last = 0;
foreach (var t in coll)
{
last = t;
yield return t;
}
yield return last * 10 + item;
}
A bit late to this party, but here are a couple ideas.
First, consider solving the more general problem:
public static IEnumerable<A> AggregateSequence<S, A>(
this IEnumerable<S> items,
A initial,
Func<A, R, A> f)
{
A accumulator = initial;
yield return accumulator;
foreach(S item in items)
{
accumulator = f(accumulator, item);
yield return accumulator;
}
}
And now your program is just new[]{2, 3, 4}.AggregateSequence(1,
(a, s) => a * 10 + s).ToArray()
However that lacks the "fluency" you want and it assumes that the same operation is applied to every element in the sequence.
You are right to note that deeply nested iterator blocks are problematic; they have quadratic performance in time and linear consumption of stack, both of which are bad.
Here's an entertaining way to implement your solution efficiently.
The problem is that you need both cheap access to the "right" end of the sequence, in order to do an operation on the most recently added element, but you also need cheap access to the left end of the sequence to enumerate it. Normal queues and stacks only have cheap access to one end.
Therefore: start by implementing an efficient immutable double-ended queue. This is a fascinating datatype; I have an implementation here using finger trees:
https://blogs.msdn.microsoft.com/ericlippert/2008/01/22/immutability-in-c-part-10-a-double-ended-queue/
https://blogs.msdn.microsoft.com/ericlippert/2008/02/12/immutability-in-c-part-eleven-a-working-double-ended-queue/
Once you have that, your operations are one-liners:
static IDeque<T> StartWith<T>(T t) => Deque<T>.Empty.EnqueueRight(t);
static IDeque<T> Op<T>(this IDeque<T> d, Func<T, T> f) => d.EnqueueRight(f(d.PeekRight()));
static IDeque<int> Times10Plus(this IDeque<int> d, int j) => d.Op(i => i * 10 + j);
Modify IDeque<T> and Deque<T> to implement IEnumerable<T> in the obvious way and you then get ToArray for free. Or do it as an extension method:
static IEnumerable<T> EnumerateFromLeft(this IDeque<T> d)
{
var c = d;
while (!c.IsEmpty)
{
yield return c.PeekLeft();
c = c.DequeueLeft();
}
}
You could do the following:
public static class MySequenceExtensions
{
public static IReadOnlyList<int> Times10Plus(
this IReadOnlyList<int> sequence,
int value) => Add(sequence,
value,
v => sequence[sequence.Count - 1] * 10 + v);
public static IReadOnlyList<T> Starts<T>(this T first)
=> new MySequence<T>(first);
public static IReadOnlyList<T> Add<T>(
this IReadOnlyList<T> sequence,
T item,
Func<T, T> func)
{
var mySequence = sequence as MySequence<T> ??
new MySequence<T>(sequence);
return mySequence.AddItem(item, func);
}
private class MySequence<T>: IReadOnlyList<T>
{
private readonly List<T> innerList;
public MySequence(T item)
{
innerList = new List<T>();
innerList.Add(item);
}
public MySequence(IEnumerable<T> items)
{
innerList = new List<T>(items);
}
public T this[int index] => innerList[index];
public int Count => innerList.Count;
public MySequence<T> AddItem(T item, Func<T, T> func)
{
Debug.Assert(innerList.Count > 0);
innerList.Add(func(item));
return this;
}
public IEnumerator<T> GetEnumerator() => innerList.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
Note that I'm using IReadOnlyList to make it possible to index into the list in a performant way and be able to get the last element if needed. If you need a lazy enumeration then I think you are stuck with your original idea.
And sure enough, the following:
var a = 1.Starts().Times10Plus(2).Times10Plus(3).Times10Plus(4).ToArray();
Produces the expected result ({1, 12, 123, 1234}) with, what I think is, reasonable performance.
You can do like this:
public interface ISequence
{
ISequenceOp StartWith(int i);
}
public interface ISequenceOp
{
ISequenceOp Times10Plus(int i);
int[] ToArray();
}
public class Sequence : ISequence
{
public ISequenceOp StartWith(int i)
{
return new SequenceOp(i);
}
}
public class SequenceOp : ISequenceOp
{
public List<int> Sequence { get; set; }
public SequenceOp(int startValue)
{
Sequence = new List<int> { startValue };
}
public ISequenceOp Times10Plus(int i)
{
Sequence.Add(Sequence.Last() * 10 + i);
return this;
}
public int[] ToArray()
{
return Sequence.ToArray();
}
}
An then just:
var x = new Sequence();
var a = x.StartWith(1).Times10Plus(2).Times10Plus(3).Times10Plus(4).ToArray();

Replace, Insert, Delete operations on IEnumerable

I have a library that only accepts a proprietary immutable collection type. I would like to have a function that accepts one of these collections and performs some changes to this collection by returning a new collection that contains the changes made.
I would like to use a LINQ syntax instead of copying this collection to a List and back.
Add operations is easy for me: concat the enumerable with another one.
But what about Replace (at the given index, return the value given instead of that IEnumerable's value), Insert (at given index, return the given value and then continue iterating over the IEnumerable) or Delete (at given index, skip the IEnumerable's value)?
Are there functions like this available in the .NET framework or in another library? If not, how would I go about implementing these functions?
You can make your own extensions for these operations:
Add
public static IEnumerable<T> Add<T>(this IEnumerable<T> enumerable, T value)
{
foreach (var item in enumerable)
yield return item;
yield return value;
}
or:
public static IEnumerable<T> Add<T>(this IEnumerable<T> enumerable, T value)
{
return enumerable.Concat(new T[] { value });
}
Insert
public static IEnumerable<T> Insert<T>(this IEnumerable<T> enumerable, int index, T value)
{
int current = 0;
foreach (var item in enumerable)
{
if (current == index)
yield return value;
yield return item;
current++;
}
}
or
public static IEnumerable<T> Insert<T>(this IEnumerable<T> enumerable, int index, T value)
{
return enumerable.SelectMany((x, i) => index == i ? new T[] { value, x } : new T[] { x });
}
Replace
public static IEnumerable<T> Replace<T>(this IEnumerable<T> enumerable, int index, T value)
{
int current = 0;
foreach (var item in enumerable)
{
yield return current == index ? value : item;
current++;
}
}
or
public static IEnumerable<T> Replace<T>(this IEnumerable<T> enumerable, int index, T value)
{
return enumerable.Select((x, i) => index == i ? value : x);
}
Remove
public static IEnumerable<T> Remove<T>(this IEnumerable<T> enumerable, int index)
{
int current = 0;
foreach (var item in enumerable)
{
if (current != index)
yield return item;
current++;
}
}
or
public static IEnumerable<T> Remove<T>(this IEnumerable<T> enumerable, int index)
{
return enumerable.Where((x, i) => index != i);
}
Then you can make calls like this:
IEnumerable<int> collection = new int[] { 1, 2, 3, 4, 5 };
var added = collection.Add(6); // 1, 2, 3, 4, 5, 6
var inserted = collection.Insert(0, 0); // 0, 1, 2, 3, 4, 5
var replaced = collection.Replace(1, 22); // 1, 22, 3, 4, 5
var removed = collection.Remove(2); // 1, 2, 4, 5
The question is a little broad, so I'll demonstrate a possibility for a Replace method. There are no methods for that in the framework that replace something in an IEnumerable, as IEnumerable should represent an immutable sequence.
So a naive way to return a new IEnumerable with replaced elements:
public static class Extensions
{
public static IEnumerable<T> Replace<T>(this IEnumerable<T> source, T oldValue, T newValue)
{
return source.Select(element => element == oldValue ? newValue : element);
}
}
This will iterate through the source sequence and return the source elements except for those who Equal the oldValue. Note that this uses the == operator and how this works depends on the type argument for T.
Also note that this uses deferred execution. The source sequence is only enumerated when you start to enumerate the resulting IEnumerable. So if you change the source sequence after a call to Replace, the resulting sequence will yield this change, too.
Implementations for Insert and Delete are straight forward, too, though you'll need to count an index in the source sequence.
IEnumerable is by definition a immutable enumerable collection of elements of a given type. Immutable means that you cannot modify it directly and you always have to create a new instance.
You can however use the yield keyword to implement this behavior, preferably using extension methods.
For example replace could look like this:
public static IEnumerable<T> ReplaceAt<T>(this IEnumerable<T> collection, int index, T item)
{
var currentIndex = 0;
foreach (var originalItem in collection)
{
if (currentIndex != index)
{
//keep the original item in place
yield return originalItem;
}
else
{
//we reached the index where we want to replace
yield return item;
}
currentIndex++;
}
}
For a functional, more LINQ-ey feeling solution, inspired by Arturo's answer:
public static IEnumerable<T> Replace<T>(this IEnumerable<T> enumerable, Func<T, bool> selector, T value)
{
foreach (var item in enumerable)
{
yield return selector(item) ? value : item;
}
}
Used like this: var newEnumerable = oldEnumerable.Replace(x => x.Id == 1, newItem)

Trying to convert IList to List in order to AddRange

I have a IList. I try to call ToList and then AddRange.
However, the ToList() overwrite all the results. How come?
private void AddAliasesThatContainsCtid(string ctid, IList<MamConfiguration_V1> results)
{
...
foreach (var alias in aliases)
{
var aliasId = "#" + alias;
results.ToList().AddRange(mMaMDBEntities.MamConfigurationToCTIDs_V1.Where(item => item.CTID == aliasId)
.Select(item => item.MamConfiguration_V1)
.ToList());
}
}
.ToList() does not convert an IEnumerable<T> to a List<T>, it creates and returns a new list filled with the values of the enumerable.
So your result.ToList() will create a new list and fill it with some data. But it will not change the contents of the object referenced by the result parameter.
In order to actually change the contents of the result parameter you have to use the .Add method of it or if your design allows it change the type of result to List<..>.
Your code is equivalent:
// Create new List by calling ToList()
var anotherList = results.ToList();
anotherList.AddRange(...);
So, you actually add items into anotherList, not result list at all.
To get the correct result, two approaches:
1:
Declare results as out and assign back:
results = anotherList;
Or:
results = results.ToList().AddRange(...)
2:
Use Add method supported by IList instead of AddRange
It's simple:
public static class ListExtensions
{
public static IList<T> AddRange<T>(this IList<T> list, IEnumerable<T> range)
{
foreach (var r in range)
{
list.Add(r);
}
return list;
}
}
Although IList<T> doesn't have an AddRange(), it does have Add(), so you could write an extension method for IList<T> that would let you add a range to it.
If you did, your code would become:
private void AddAliasesThatContainsCtid(string ctid, IList<MamConfiguration_V1> results)
{
...
results.AddRange(mMaMDBEntities.MamConfigurationToCTIDs_V1
.Where(item => item.CTID == aliasId)
Select(item => item.MamConfiguration_V1));
}
}
Compilable sample implementation:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
internal class Program
{
static void Main()
{
IList<string> list = new List<string>{"One", "Two", "Three"};
Print(list);
Console.WriteLine("---------");
var someMultiplesOfThree = Enumerable.Range(0, 10).Where(n => (n%3 == 0)).Select(n => n.ToString());
list.AddRange(someMultiplesOfThree); // Using the extension method.
// Now list has had some items added to it.
Print(list);
}
static void Print<T>(IEnumerable<T> seq)
{
foreach (var item in seq)
Console.WriteLine(item);
}
}
// You need a static class to hold the extension method(s):
public static class IListExt
{
// This is your extension method:
public static IList<T> AddRange<T>(this IList<T> #this, IEnumerable<T> range)
{
foreach (var item in range)
#this.Add(item);
return #this;
}
}
}

foreach with index [duplicate]

This question already has answers here:
How do you get the index of the current iteration of a foreach loop?
(35 answers)
Closed 9 years ago.
Is there a C# equivalent of Python's enumerate() and Ruby's each_with_index?
I keep this extension method around for this:
public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
{
var i = 0;
foreach (var e in ie) action(e, i++);
}
And use it like so:
var strings = new List<string>();
strings.Each((str, n) =>
{
// hooray
});
Or to allow for break-like behaviour:
public static bool Each<T>(this IEnumerable<T> ie, Func<T, int, bool> action)
{
int i = 0;
foreach (T e in ie) if (!action(e, i++)) return false;
return true;
}
var strings = new List<string>() { "a", "b", "c" };
bool iteratedAll = strings.Each ((str, n)) =>
{
if (str == "b") return false;
return true;
});
You can do the following
foreach (var it in someCollection.Select((x, i) => new { Value = x, Index = i }) )
{
if (it.Index > SomeNumber) //
}
This will create an anonymous type value for every entry in the collection. It will have two properties
Value: with the original value in the collection
Index: with the index within the collection
The C# foreach doesn't have a built in index. You'll need to add an integer outside the foreach loop and increment it each time.
int i = -1;
foreach (Widget w in widgets)
{
i++;
// do something
}
Alternatively, you could use a standard for loop as follows:
for (int i = 0; i < widgets.Length; i++)
{
w = widgets[i];
// do something
}
I like being able to use foreach, so I made an extension method and a structure:
public struct EnumeratedInstance<T>
{
public long cnt;
public T item;
}
public static IEnumerable<EnumeratedInstance<T>> Enumerate<T>(this IEnumerable<T> collection)
{
long counter = 0;
foreach (var item in collection)
{
yield return new EnumeratedInstance<T>
{
cnt = counter,
item = item
};
counter++;
}
}
and an example use:
foreach (var ii in new string[] { "a", "b", "c" }.Enumerate())
{
Console.WriteLine(ii.item + ii.cnt);
}
One nice thing is that if you are used to the Python syntax, you can still use it:
foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))
Aside from the LINQ answers already given, I have a "SmartEnumerable" class which allows you to get the index and the "first/last"-ness. It's a bit ugly in terms of syntax, but you may find it useful.
We can probably improve the type inference using a static method in a nongeneric type, and implicit typing will help too.
My solution involves a simple Pair class I created for general utility, and which is operationally essentially the same as the framework class KeyValuePair. Then I created a couple extension functions for IEnumerable called Ordinate (from the set theory term "ordinal").
These functions will return for each item a Pair object containing the index, and the item itself.
public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs)
{
return lhs.Ordinate(0);
}
public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs, Int32 initial)
{
Int32 index = initial - 1;
return lhs.Select(x => new Pair<Int32, X>(++index, x));
}
No, there is not.
As other people have shown, there are ways to simulate Ruby's behavior. But it is possible to have a type that implements IEnumerable that does not expose an index.
This is your collection
var values = new[] {6, 2, 8, 45, 9, 3, 0};
Make a range of indexes for this collection
var indexes = Enumerable.Range(0, values.Length).ToList();
Use the range to iterate with index
indexes.ForEach(i => values[i] += i);
indexes.ForEach(i => Console.Write("[{0}] = {1}", i, values[i]));
I just figured out interesting solution:
public class DepthAware<T> : IEnumerable<T>
{
private readonly IEnumerable<T> source;
public DepthAware(IEnumerable<T> source)
{
this.source = source;
this.Depth = 0;
}
public int Depth { get; private set; }
private IEnumerable<T> GetItems()
{
foreach (var item in source)
{
yield return item;
++this.Depth;
}
}
public IEnumerator<T> GetEnumerator()
{
return GetItems().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
// Generic type leverage and extension invoking
public static class DepthAware
{
public static DepthAware<T> AsDepthAware<T>(this IEnumerable<T> source)
{
return new DepthAware<T>(source);
}
public static DepthAware<T> New<T>(IEnumerable<T> source)
{
return new DepthAware<T>(source);
}
}
Usage:
var chars = new[] {'a', 'b', 'c', 'd', 'e', 'f', 'g'}.AsDepthAware();
foreach (var item in chars)
{
Console.WriteLine("Char: {0}, depth: {1}", item, chars.Depth);
}
It depends on the class you are using.
Dictionary<(Of <(TKey, TValue>)>) Class For Example Support This
The Dictionary<(Of <(TKey, TValue>)>) generic class provides a mapping from a set of keys to a set of values.
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<(Of <(TKey, TValue>)>) structure representing a value and its key. The order in which the items are returned is undefined.
foreach (KeyValuePair kvp in myDictionary) {...}

Categories

Resources