Naty Bizz
Naty Bizz

Reputation: 2342

How to set the value to the first N elements of a list?

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

Answers (6)

Artiom
Artiom

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

sab669
sab669

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

Markus
Markus

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

rae1
rae1

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

Servy
Servy

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

Katie Kilian
Katie Kilian

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

Related Questions