ForEach with index in C# [duplicate] - c#

This question already has answers here:
List<T>.ForEach with index
(12 answers)
Closed 4 years ago.
I'm need to call function from ForEach in Linq, and I need to send a string parameter and the Index from the ForEach
List<string> listString= new List<string>();
listString.ForEach((str, i) => { Func(str, i) , i++});
private ResponseBase Func(string s,int i)
{

You could try something like this:
var responses = listString.Select((value, index) => Func(value, index)).ToList();
The above for each item in listString would call the method you have defined. The results of all calls would be stored in a list and you could access them by using the corresponding index.

I'm a big fan of LINQ. Really.
But in this cases, when you are accessing an already existing List, I would go for an old fashioned for loop.
for(var i = 0; i < listString.Count; i++)
Func(listString[i], i);
It's not longer, it's far more efficient (it's probably not a problem, but let's remember this), and it just gets the job done.

You can introduce a variable and then increment it:
List<String> values = new List<String>();
int indexTracker = 0;
values.ForEach(x=> { Func(x, indexTracker++); });
Or you can write the following extension method:
public static void ForEach<T>(this List<T> input, Action<T, int> action)
{
for(int i = 0; i < input.Count; i++)
{
action(input[i], i);
}
}
and then use it like
values.ForEach((x,i)=> Func(x, i));

Related

c# create a .forEach() Method using actions [duplicate]

This question already has answers here:
Why does assignment to parameter not change object?
(4 answers)
Closed 8 months ago.
I'm trying to create a method that loops through an array and executes some actions I wrote with a lambda expression. Somehow I don't think I understood how to use actions correctly because my code just results in a bunch of "null" objects.
Does somebody know what I am doing wrong?
public void forEach(Action<Neuron> action)
{
for(int i = 0; i < this.Neurons.Length; i++)
{
action(this.Neurons[i]);
}
}
public void CreateNeurons(int AmountOfNeurons)
{
this.Neurons = new Neuron[AmountOfNeurons];
this.forEach(x => x = new Neuron(AmountOfNeurons));
}
In your delegate, setting x = ... only changes the value of that local parameter: it does nothing to the array itself. You would end up with the same problem if you used a for loop like this:
var a = new[] { 1, 2, 3};
for (int i = 0; i < a.Length; i++)
{
var x = a[i];
x = 5; // this does nothing to `a[i]`
}
Notably, a foreach loop would warn you if you tried to do this:
foreach (var x in a)
{
x = 5; // CS1656: Cannot assign to 'x' because it is a foreach variable.
}
This supports Dai's comment: you really shouldn't be defining your own forEach method. There are plenty of better, more idiomatic ways to do anything you'd want to do with a method like this. A foreach construct would have told you exactly what you were doing wrong, for example. And creating an array with a bunch of items is typically simpler with LINQ:
this.Neurons = Enumerable.Range(0, AmountOfNeurons)
.Select(_ => new Neuron(AmountOfNeurons))
.ToArray();

How I can get elements from dictionary and add into array? [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 2 years ago.
I have IDictionary<string, int>. I need to get keys and values from dictionary in string format and add into string[] array. I need to do it because I want to pass that text in function and that function takes string array.
I have that code for getting value:
foreach (KeyValuePair<string, int> kvp in dict)
{
dataList.Add(kvp.Key + " " + kvp.Value.ToString());
}
I've created list and add in that list keys and values. After I was thinking to create for loop and from list add elements into array, but have error. Loop:
string[] txtArr;
for (int i = 0; i < dataList.Count; i++)
{
txtArr[i] = dataList[i];
}
Error: System.NullReferenceException. I don't understand where is the problem. From what I read about that error, I understood it raised because something is null. But if I'm trying print in console dictionary or list all is OK, there isn't null, also i is int and = 0. Where is the problem?
Your array is not instantiated, dude:
string[] txtArr = new string[dataList.Count];
for (int i = 0; i < dataList.Count; i++)
{
txtArr[i] = dataList[i];
}
or you can do it like this:
string[] txtArr = dataList.ToArray();
or you can do it like this:
string[] txtArr = dict.ToList().Select(x => x.Value).ToArray();
You have to initialize the string array.
string[] txtArr = new string[dataList.Count];

Why struct properties cannot be changed if they are in a list? [duplicate]

This question already has answers here:
In C#, why can't I modify the member of a value type instance in a foreach loop?
(8 answers)
Closed 3 years ago.
Please consider the following code:
public class Program {
public struct A
{
public int Prop {get;set;}
}
public static void Main()
{
var obj = new A();
obj.Prop = 10;
var list = new List<A>(){obj};
foreach(var l in list) {
l.Prop = 20; //here I'm getting compile time error "Cannot modify members of 'l' because it is a 'foreach iteration variable'"
}
}
}
So my question is: why struct properties cannot be assigned while iterating over a list of structs?
Please note that even when iterating with simple for like this:
for (int i=0; i<list.Count(); ++i)
list[i].Prop = 20;
I'm still getting compile time error...
You cannot modify collection over which you are iterating with foreach.
Instead you should use for loop, which allows that:
for(int i = 0; i < list.Length; i++)
{
list[i].Prop = 200;
}
You can refer to this question: Why can't we assign a foreach iteration variable, whereas we can completely modify it with an accessor?

what is the fastest way to transfer items from an array? [duplicate]

This question already has answers here:
C# - For vs Foreach - Huge performance difference
(2 answers)
Closed 4 years ago.
Not sure if i phrased the title correctly but say i have a method such as:
public static string[] ByteArrayToStringArray(byte[] buffer)
{
//code here
}
would it be better to do
List<string> list = new List<string>();
for (int i = 0; i < buffer.Length; i++)
{
list.Add(buffer[i].ToString());
}
return list.ToArray();
or would it be better to do
List<string> list = new List<string>();
foreach (byte b in buffer)
{
list.Add(b.ToString());
}
return list.ToArray();
which is faster or is there no difference between them?
Like described in this question, iterating an array with a for loop is less cheaper than using a foreach.
You also could improve your code by omitting the list. Just create the array before and set the string items during the loop. Here is the improved version:
public static string[] ByteArrayToStringArray(byte[] buffer)
{
string[] ret = new string[buffer.Length];
for (int i = 0; i < buffer.Length; i++)
{
ret[i] = buffer[i].ToString();
}
return ret;
}
Note that there are also very compact LINQ options like
buffer.Select(c => c.ToString()).ToArray();
but LINQ queries are not best in terms of performance.
EDIT:
Referring to the discussion with Gusman at the comments below, it is possible to improve the performance even more by using a while loop.

Change ref element value with Array.ForEach?

I'm trying to use the Array.ForEach() extension method to loop through for a list of filtered elements from an array and then modify those values, unfortunately that doesn't seem to work I'm guessing because it doesn't actually modify the reference value of each element.
Is there any way to do this besides storing the results of the Array.ForEach() into a seperate array and then cloning that array to the original array? Also I know I could obviously do all of this without cloning if I use a for loop but if I could do it this way it would be cleaner and would be less code.
Here's the snippet:
Array.ForEach(Array.FindAll(starts, e => e < 0), e => e = 0);
ForEach simply isn't intended to do this - just like you wouldn't be able to do this with a foreach loop.
Personally I'd just use a for loop - it's easy to read and clear:
for (int i = 0; i < array.Length; i++)
{
// Alternatively, use Math.Max to pull up any negative values to 0
if (array[i] < 0)
{
array[i] = 0;
}
}
It really is simple - anyone will be able to understand it.
Now you could write your own extension method instead. You could write one to replace all values which satisfy a predicate with a fixed value, or you could write one to replace all values entirely... but I don't think it's really worth it. As an example of the latter:
public static void ReplaceElements<T>(this T[] array,
Func<T, T> replacementFunction)
{
// TODO: Argument validation
for (int i = 0; i < array.Length; i++)
{
array[i] = replacementFunction(array[i]);
}
}
Then call it with:
starts.ReplaceElements(x => Math.Max(x, 0));
I'd personally still use the for loop though.
(You could potentially change the above very slightly to make it take IList<T> and use Count instead. That would still work with arrays, but also List<T> etc too.)
You can do that with ref and delegates. However, I don't think it adds much value.
public delegate void RefAction<T>(ref T value);
public static void ForEachRef<T>(this T[] array, RefAction<T> action)
{
for (int i = 0; i < array.Length; ++i) action(ref array[i]);
}
You can use it as follows:
var myArray = new int[];
myArray.ForEachRef((ref int i) => i = whateverYouLike());
From the standpoint of possibility, there could be an interface IRefEnumerable<T> which iterates some container with assignable elements.
array = array.Select(x => (x < 0) ? 0: x).ToArray();

Categories

Resources