Reputation: 2342
Given a list I want to set a value (in my case the red color) to the first 3 elements; the rest of the elements will have another color
I have this so far
int top3=0;
foreach (MyCustomObject gb in Data)
{
if (top3 <= 3)
{
gb.NodeColor = Colors.Green;
}
else
{
gb.NodeColor = Colors.Red;
}
top3++;
}
I don't like this approach, Is there a way to do this with LINQ?
Fyi my list is ordered ascending and MyCustomObject is not the real name of my class
Upvotes: 0
Views: 3347
Reputation: 7837
Due to the fact IEnumerable doesn't have ForEach extension may be it's better to go with for loop for instance. But if you really need LINQ than you need to implement an extension for IEnumerable
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> source,
Action<T> action){
foreach (var e in source){
action(e);
yield return e;
}
}
than you can use it in next way
Data.Take(4).ForEach(data=>data.Color=Colors.Red);
Data.Skip(4).ForEach(data=>data.Color=Colors.Green);
Upvotes: -1
Reputation: 4104
You could try something like this maybe? Not much cleaner...
for (int i = 0; i < elementsToSet; i++)
array[i].NodeColor = Colors.Green;
for (elementsToSet; elementsToSet < array.Length; elementsToSet++)
array[elementsToSet].NodeColor = Colors.Red;
Edit: Just noticed you wanted LINQ... Woops
Upvotes: 4
Reputation: 22456
You can solve it using the an overload of the Select extension method:
var result = Data.Select((x, index) => {
x.NodeColor = index < 3 ? Colors.Red : Colors.Green;
return x;
}).ToArray();
However, it is up to you whether this is really better than a plain loop as it obfuscates the fact that the values of the input data are changed in the selector function. So cloning the data might be a better approach in the selector function.
Upvotes: 2
Reputation: 6144
You could do,
int top3 = 3; // Although I think you actually want top4 based on 'i <= 3'
Data.Take(top3).ToList().ForEach(gb => gb.NodeColor = Colors.Green);
Data.Skip(top3).ToList().ForEach(gb => gb.NodeColor = Colors.Red);
Although in this case you might end up traversing the Data
source twice; might be better to just use a for
as @Charlie Kilian mentions.
Upvotes: 0
Reputation: 203829
While I would normally use two for
loops for this, as was mentioned in an earlier answer, you can use a bit of LINQ if you really want to throw some in there:
foreach (var i in Enumerable.Range(0, 3))
Data[i].NodeColor = Colors.Green;
foreach (var i in Enumerable.Range(3, Data.Length - 3))
Data[i].NodeColor = Colors.Red;
Upvotes: 2
Reputation: 6995
Why not just a regular for
loop?
for (int i = 0; i < Data.Count(); i++ )
{
Data[i].NodeColor = (i < 3 ? Colors.Red : Colors.Green);
}
I personally think that is more readable than it would be in LINQ, but as always, your mileage may vary.
Upvotes: 12