How can I prevent duplication of a common loop in my solution? - c#

I have this loop based on a jagged array below which I will need to use more than once at different places.
How can I prevent myself to rewrite this loop again and again so that I will duplicate it?
foreach (int[] columns in rowsAndColumns)
{
foreach (int element in columns)
{
}
}

You can write
foreach (int element in rowsAndColumns.SelectMany(col => col))
{
// ...
}
instead. If you don’t like to have to type that all the time, you can abstract it into a helper method:
foreach (int element in rowsAndColumns.Flatten())
{
// ...
}
// [...]
public IEnumerable<T> Flatten(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(e => e);
}

It depends on what you want to do, but if you want to perform an action on each int, you could go for something like the extension below. Some null checking might be advisible.
static class RowColExtension
{
public static void Each(this int[][] rowCols, Action<int> a)
{
foreach (var r in rowCols)
{
foreach (var c in r)
{
a(c);
}
}
}
}

It depends on what you want to do in the loop. I would approach it like this (untested code out of my head!):
public static class MyHelper {
public static void ForEach(this IEnumerable<int[]> rowsAndColumns, Action<int> action) {
foreach (int[] columns in rowsAndColumns) {
foreach (int element in columns) {
action(element);
}
}
}
}
Now you can call it like this:
rowsAndColumns.ForEach(e => Console.WriteLine(e));

Extension method:
// It's late and I'm tired, the array declaration might be off.
public static void Visit(this int[][] array, Action<int> visitor)
{
foreach (int[] columns in array)
{
foreach (int element in columns)
{
visitor(element);
}
}
}
myArray.Visit(elem => Console.WriteLine(elem));
You can use Action<int,int> to get the row too.

Since you are iterating over all elements without regard to the row or column you should turn your jagged array into a first class data structure and implement IEnumerable to iterate over the collection using foreach. The same first-class data structure can support one-argument and two-argument indexers, range checking, etc.
Edit:
Here is one approach to use abstraction instead of manipulating low-level data structures. This assumes the jagged array was allocated elsewhere. Either way, the point is we can now use foreach directly on the data structure:
public class JaggedArray : IEnumerable<int>
{
private int[][] array;
public JaggedArray(int[][] array)
{
this.array = array;
}
public int this[int row, int column]
{
get { return array[row][column]; }
set { array[row][column] = value; }
}
public IEnumerable<int[]> Rows
{
get { return array; }
}
public IEnumerator<int> GetEnumerator()
{
foreach (var row in array)
foreach (var item in row)
yield return item;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

Related

Custom extension methods on IEnumerable<T>

In my project we are getting different list and array of elements and need to pick alternative for those list and array for example if my list consist of
string[] toys= { "car", "bat-mask", "halloween-toys", "marvel-toys", "transformer" };
now it may be a list of hundreds of elements my problems is to choose alternative from above list like if i have configuratioin to pick one after another i.e car after that skip bat-mask and pick halloween-toys this is my first priority and after that i make it configurable like how many item to skip in between like one item or two items etc.
Reason to use it as extension because it will be use inside complete app and i simply need it access like var myList = toys.customExtensionMethods();
You can use that:
using System.Linq;
static public class IEnumerableHelper
{
static public IEnumerable<T> customExtensionMethods<T>(this IEnumerable<T> items,
T takeFirst,
int skipCount)
{
var list1 = items.SkipWhile(item => !item.Equals(takeFirst));
var list2 = list1.Skip(skipCount + 1).Take(1);
return list1.Take(1).Concat(list2);
}
}
Test 1
static void Test()
{
string[] toys = { "car", "bat-mask", "halloween-toys", "marvel-toys", "transformer" };
var list = toys.customExtensionMethods("car", 1);
foreach ( var item in list )
Console.WriteLine(item);
}
Output:
car
halloween-toys
Test 2
var list = toys.customExtensionMethods("bat-mask", 2);
Output
bat-mask
transformer
If i am not wrong, inside your extension method you want to get array element with no Of skip value passed.
public static class ExtensionMethod
{
public static string[] CustomExtensionMethods(this string[] myData, int NoofSkip)
{
var newData = new List<string>();
for (int i = 0; i < myData.Length; i++ )
{
newData.Add(myData[i]);
i = i + NoofSkip;
}
return newData.ToArray();
}
}
Call Method:
var data = toys.CustomExtensionMethods(1);
OutPut:
{ "car", "halloween-toys", "transformer" };
I hope I understood your question correctly. You are intending to create an extension method which takes an input 'searchterm' and a count skip count. The method searches for the item in the list, skips the next n items and returns the new item. You could do as the following.
public static class Extensions
{
public static T PickAlternative<T>(this IEnumerable<T> source,string item,int skipCount)
{
return source.SkipWhile(x=> !x.Equals(item)).Skip(skipCount).First();
}
}
Example,
toys.PickAlternative("bat-mask",3);
toys.PickAlternative("car",2);
Output
transformer
halloween-toys
public static class EnumerableExtensions
{
public static IEnumerable<T> PickAlternate<T>(this IEnumerable<T> source, int skip)
{
int? currentlySkipped = null;
foreach (var item in source)
{
if (!currentlySkipped.HasValue || currentlySkipped == skip)
{
currentlySkipped = 0;
yield return item;
}
else
{
currentlySkipped++;
}
}
}
}

C# - Set that returns index when adding new element

I am looking for a collection that matches the following conditions:
Elements in the collection are never repeated. That is, something ISet<T>-like.
The order of elements in the collection does not change unless elements are removed from the collection. (In my use-case I never remove any elements at all).
I want to be able to get the index of the element I have just added. Due to the requirement 1 that would mean: receiving the index of the element if it already exists in the collection or receiving something like .Count if the element does not exist.
I tried using OrderedSet collection and then getting the index of the element with a one-liner extension method. The problem is it takes around 100ms on my machine every time I try to add a new element in a collection that already consists of couple of thousands. That is a big deal when adding lots of elements into a huge collection.
I suspect that getting the index could be done in the same place where adding the element is. Therefore, I am looking for a probably existing collection for such purpose.
Thank you in advance.
How about:
public class SpecialList<T> : List<T>
{
public new int Add(T Item)
{
if (Contains(Item))
{
return IndexOf(Item);
}
else
{
base.Add(Item);
return Count - 1;
}
}
}
Alright, so considering this problem I tried 4 solutions:
Making an OrderedSet<T> with an AddWithIndex extension method
Making a HashSet<T> with an AddWithIndex extension method. Although it doesn't guarantee the order of the elements it could still be useful in some scenarios.
Extending the List<T> class the way JerryM proposed
Writing my own IndexedSet<T> class
All of the tests were taken on the following piece of code:
static void Main(string[] args)
{
var elements = Enumerable.Range(0, 1000000).Select(i => i.ToString()).ToList();
//Initialize collection here
//...
var sw = new Stopwatch();
sw.Start();
foreach (var element in elements)
{
//Add element to collection here
//...
}
sw.Stop();
Console.WriteLine("Elapsed time: {0}", sw.Elapsed);
}
This test only covers the case where all elements are different and is not really representative when you have lots of repeating elements.
Test 1.
AddWithIndex extension method for HashSet<T> (it is basically the same for OrderedSet<T>):
static class HashSetExtensions
{
public static int AddWithIndex<T>(this HashSet<T> set, T element)
{
if (set.Add(element))
{
return set.Count - 1;
}
return set.IndexOf(element);
}
public static int IndexOf<T>(this HashSet<T> set, T element)
{
int index = 0;
foreach (var item in set)
{
if (element.Equals(item))
{
return index;
}
index++;
}
return -1;
}
}
This gave me 0.3842932 seconds on HashSet<T> and 1.1972123 seconds on OrderedSet<T>.
Test 2.
Deriving from List<T> the way JerryM proposed results in 7.6716346 seconds on a collection of 20000 elements (that is 50 times less elements than in collections used for other tests) and roughly infinite time on the original 1000000 elements.
Test 3.
Finally, I created the following IndexedSet<T> collection which is basically a wrapper on both List<T> and HashSet<T>:
public class IndexedSet<T> : IReadOnlyList<T>, IList<T>
{
private readonly List<T> _list = new List<T>();
private readonly HashSet<T> _set = new HashSet<T>();
public IEnumerator<T> GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _list.GetEnumerator();
}
public int Add(T item)
{
if (_set.Add(item))
{
_list.Add(item);
return _list.Count - 1;
}
return _list.IndexOf(item);
}
void ICollection<T>.Add(T item)
{
Add(item);
}
public void Clear()
{
_list.Clear();
_set.Clear();
}
public bool Contains(T item)
{
return _set.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}
public bool Remove(T item)
{
bool remove = _set.Remove(item);
if (remove)
_list.Remove(item);
return remove;
}
public int Count => _list.Count;
public bool IsReadOnly => false;
public int IndexOf(T item)
{
return _list.IndexOf(item);
}
public void Insert(int index, T item)
{
throw new NotImplementedException();
}
public void RemoveAt(int index)
{
T item = _list[index];
_list.RemoveAt(index);
_set.Remove(item);
}
public T this[int index]
{
get { return _list[index]; }
set
{
T item = _list[index];
_set.Remove(item);
_list[index] = value;
_set.Add(value);
}
}
}
This gave me 0.3558594 seconds (that is even a bit faster than extension for HashSet<T>) and guaranteed the order of the elements (just like OrderedSet<T>).
Hopefully, this would be useful for someone in future.

Iterating an array with foreach backwards without using extension method

After making a search at the Google, I found this discussion:
Possible to iterate backwards through a foreach?
But in the answers there is used extension method .Reverse(). With reverse, the list of objects, for ie. List of Strings, wtill be reversed first, and foreach doesn't reverse the list with my understoodment? If I got list "Cat", "Dog", and use .Reverse() -method, the list will be "Dog", "Cat", and foreach starts from the 0 element till the lenght-1 -element and that's what I'm not looking for. I would want to know, if there was any way to reverse foreach iteration order, to start from lenght-1 down to 0.
if there was any way to reverse foreach iteration order, to start from length-1 down to 0
Not for a List<T>. The implementation of GetEnumerator() returns an enumerator that enumerates from beginning to end - there's no way to override that.
With a custom collection, then you'd just have to use a different enumerator that could go backwards, but there's no way to override the implementation that List<T> uses.
The Reverse method will copy the list first:
public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
return ReverseIterator<TSource>(source);
}
static IEnumerable<TSource> ReverseIterator<TSource>(IEnumerable<TSource> source) {
Buffer<TSource> buffer = new Buffer<TSource>(source);
for (int i = buffer.count - 1; i >= 0; i--) yield return buffer.items[i];
}
But you can do an extension method yourself:
public static IEnumerable<TSource> Backwards<TSource>(this IList<TSource> source) {
for (var i = source.Count - 1; i >= 0; --i)
yield return source[i];
}
And then use it like that:
foreach (var item in array.Backwards())
Console.WriteLine(item); // Or whatever else
Or, of course, you could just do the equivalent:
for (var i = array.Length - 1; i >= 0; --i)
Console.WriteLine(array[i]); // Or whatever else
You can implement an enumerator that iterates though a list backwards. That way you can use foreach without changing the original list or creating a copy of it.
public class ReverseEnumerator<T> : IEnumerator<T> {
private IList<T> _list;
private int _index;
private T _current;
public ReverseEnumerator(IList<T> list) {
_list = list;
Reset();
}
public IEnumerator<T> GetEnumerator() {
return this;
}
public T Current {
get {
if (_index < 0 && _index >= _list.Count) throw new InvalidOperationException("Enumeration has not started. Call MoveNext.");
return _current;
}
}
public void Dispose() { }
object IEnumerator.Current { get { return Current; } }
public bool MoveNext() {
bool ok = --_index >= 0;
if (ok) _current = _list[_index];
return ok;
}
public void Reset() {
_index = _list.Count;
}
}
Usage example:
int[] a = { 1, 2, 3, 4, 5 };
foreach (int x in new ReverseEnumerator<int>(a)) {
Console.WriteLine(x);
}

C# Syntax - Example of a Lambda Expression - ForEach() over Generic List

First, I know there are methods off of the generic List<> class already in the framework do iterate over the List<>.
But as an example, what is the correct syntax to write a ForEach method to iterate over each object of a List<>, and do a Console.WriteLine(object.ToString()) on each object.
Something that takes the List<> as the first argument and the lambda expression as the second argument.
Most of the examples I have seen are done as extension methods or involve LINQ. I'm looking for a plain-old method example.
public void Each<T>(IEnumerable<T> items, Action<T> action)
{
foreach (var item in items)
action(item);
}
... and call it thusly:
Each(myList, i => Console.WriteLine(i));
Is this what you're asking for?
int[] numbers = { 1, 2, 3 };
numbers.ToList().ForEach(n => Console.WriteLine(n));
The above could also be written with less code as:
new List<SomeType>(items).ForEach(
i => Console.WriteLine(i)
);
This creates a generic list and populates it with the IEnumerable and then calls the list objects ForEach.
public static void Each<T>(this IEnumerable<T> items, Action<T> action) {
foreach (var item in items) {
action(item);
} }
... and call it thusly:
myList.Each(x => { x.Enabled = false; });
Want to put out there that there is not much to worry about if someone provides an answer as an extension method because an extension method is just a cool way to call an instance method. I understand that you want the answer without using an extension method. Regardless if the method is defined as static, instance or extension - the result is the same.
The code below uses the code from the accepted answer to define an extension method and an instance method and creates a unit test to show the output is the same.
public static class Extensions
{
public static void Each<T>(this IEnumerable<T> items, Action<T> action)
{
foreach (var item in items)
{
action(item);
}
}
}
[TestFixture]
public class ForEachTests
{
public void Each<T>(IEnumerable<T> items, Action<T> action)
{
foreach (var item in items)
{
action(item);
}
}
private string _extensionOutput;
private void SaveExtensionOutput(string value)
{
_extensionOutput += value;
}
private string _instanceOutput;
private void SaveInstanceOutput(string value)
{
_instanceOutput += value;
}
[Test]
public void Test1()
{
string[] teams = new string[] {"cowboys", "falcons", "browns", "chargers", "rams", "seahawks", "lions", "heat", "blackhawks", "penguins", "pirates"};
Each(teams, SaveInstanceOutput);
teams.Each(SaveExtensionOutput);
Assert.AreEqual(_extensionOutput, _instanceOutput);
}
}
Quite literally, the only thing you need to do to convert an extension method to an instance method is remove the static modifier and the first parameter of the method.
This method
public static void Each<T>(this IEnumerable<T> items, Action<T> action)
{
foreach (var item in items)
{
action(item);
}
}
becomes
public void Each<T>(Action<T> action)
{
foreach (var item in items)
{
action(item);
}
}
You can traverse each string in the list and even you can search in the whole generic using a single statement this makes searching easier.
public static void main(string[] args)
{
List names = new List();
names.Add(“Saurabh”);
names.Add("Garima");
names.Add(“Vivek”);
names.Add(“Sandeep”);
string stringResult = names.Find( name => name.Equals(“Garima”));
}
Standard:
foreach (Item i in allItems)
{
i.FK_ItemStatus_CustomCodeID = itemStatuses.Where(
x => x.CustomCodeID == i.ItemStatus_CustomCodeID).FirstOrDefault();
}
Lambda:
allItems.ForEach(
i => i.FK_ItemStatus_CustomCodeID =
itemStatuses.Where(
x => x.CustomCodeID == i.ItemStatus_CustomCodeID).FirstOrDefault()
);

C# Code Simplification Query: The Sequential Foreach Loops

Suppose I have some code that looks like this:
foreach(type x in list y)
{
//dostuff1(x)
}
foreach(type x in list y)
{
//dostuff2(x)
}
foreach(type x in list y)
{
//dostuff3(x)
}
foreach(type x in list y)
{
//dostuff4(x)
}
foreach(type x in list y)
{
//dostuff5(x)
}
I cannot combine things into one big for loop like this:
foreach (type x in list y)
{
//dostuff1(x)
//dostuff2(x)
//dostuff3(x)
//dostuff4(x)
//dostuff5(x)
}
Doing so would change the order. Any commentary on the best ways to make the code simpler in C#?
I imagine I could solve this problem by creating a function like this, though I'd rather leave it the way it is than force future readers of my code to understand yield:
void func(type x)
{
dostuff1(x)
yield 0;
dostuff2(x)
yield 0;
dostuff3(x)
yield 0;
dostuff4(x)
yield 0;
dostuff5(x)
yield break;
}
for (int i = 0; i<5; ++i)
{
foreach (type x in list y)
{
//Call func(x) using yield semantics, which I'm not going to look up right now
}
}
Another alternative:
List<Action<Foo>> actions = new List<Action<Foo>> {
doStuff1, doStuff2, doStuff3, doStuff4, doStuff5
};
foreach (Action<Foo> action in actions)
{
foreach (Foo x in list)
{
action(x);
}
}
Just checked, and that works. For instance:
using System;
using System.Collections.Generic;
public class Test
{
static void Main(string[] args)
{
var actions = new List<Action<string>> {
First, Second
};
foreach (var action in actions)
{
foreach (string arg in args)
{
action(arg);
}
}
}
static void First(string x)
{
Console.WriteLine("First: " + x);
}
static void Second(string x)
{
Console.WriteLine("Second: " + x);
}
}
Results of running Test.exe a b c
First: a
First: b
First: c
Second: a
Second: b
Second: c
If you have a fairly constant list of actions, you could just avoid the foreach loops, but still do the actions explicitly (haven't tested the code):
list.ForEach(action1);
list.ForEach(action2);
list.ForEach(action3);
list.ForEach(action4);
Jon Skeet's answer is excellent (I just voted it up). Here's an idea to take it one step further:
If you do this a lot, you could make an extension method called "DoActionsInOrder" (or maybe you can come up with a better name) that does this. Here's the idea:
public static void DoActionsInOrder<T>(this IEnumerable<T> stream, params Action<T> actionList)
{
foreach(var action in actionList)
{
foreach(var item in stream)
{
action(item);
}
}
}
Then, you could call it like this:
myList.DoActionsInOrder(doStuff1, doStuff2, doStuff3, doStuff4, doStuff5);
How about:
interface IDoStuff
{
void DoStuff(x);
}
List<IDoStuff> listOfActions = ...
foreach (IDoStuff iDoStuff in listOfActions)
{
foreach (type x in list y)
{
iDoStuff(x);
}
}
[edit] And yes, you should rather go for the generic solution as J.Skeet said (although you can use a generic interface instead of a delegate as well).
If you must retain the sequential nature, there's not much you can do. You could do some extension method shortcuts, but IMHO this makes for less readable code. Also, you may run into problems depending on your method signatures.
You could refactor to move the iteration to separate functions.
// Method 1
DoStuff1ToList(y);
DoStuff2ToList(y);
DoStuff3ToList(y);
DoStuff4ToList(y);
DoStuff5ToList(y);
// Do Stuff 1
foreach (var x in y)
{
// do actual stuff
}
i think this is the same as testing.ForEach(action)
so just use that if your going down this kind of route.
private static void DoDifferentStuffToThings()
{
List<string> testing = new List<string>() { "hello", "world" };
Action<string> action1 = (a) =>
{
Console.WriteLine("Action 1 {0}", a);
};
Action<string> action2 = (a) =>
{
Console.WriteLine("Action 2 {0}", a);
};
DoStuffToThings<string>(testing, action1);
DoStuffToThings<string>(testing, action2);
}
private static void DoStuffToThings<T>(IEnumerable<T> list, Action<T> dothing)
where T : class
{
foreach (var item in list)
{
dothing(item);
}
}

Categories