hello world
hello world

Reputation: 807

Map value to item from list and add the new value to the same list C#

I have an Array of colors viz.

var colorPallete = new string[]{color1, color2, color3, color4, color5};

I also have a list of objects which contains an ID. eg. var previousList<MyModel> = new List<MyModel>();

MyModel.cs

public class MyModel()
{
   public int ID {get; set;}
public string Class{get; set;}
public string Name {get; set;}
public string Color {get; set;}
}

I want to assign the objects with same ID with a certain color. And then add the assigned color as a new value to the list.

for eg:

Previous list :-

            ID :1
            Name: abc
            Class: Senior

           ID :2
            Name: xyz
            Class: Medium

            ID :3
            Name: pqr
            Class: junior

           ID :1
            Name: mno
            Class: junior

New List :-

            ID :1
            Name: abc
            Class: Senior
            Color :color1

            ID :2
            Name: xyz
            Class: Medium
            Color :color2

            ID :3
            Name: pqr
            Class: junior
            Color :color3

            ID :1
            Name: mno
            Class: junior
            Color :color1

Upvotes: 2

Views: 4376

Answers (3)

Igor Bendrup
Igor Bendrup

Reputation: 2837

If you are using List<T> (not IEnumerable<T>) and you don't want to create a new list, but need to update values in the existing list instead, you can do it with the single query. There are three ways to process your scenario (A, B, C):

var colorPallete = new string[]
{
    "Red", "Green", "Blue"
};

var list = new List<MyModel>()
{
    new MyModel() { ID = 1, Name = "model1", Class = "A", },
        new MyModel() { ID = 1, Name = "model11", Class = "AA", },
        new MyModel() { ID = 2, Name = "model2", Class = "B", },
        new MyModel() { ID = 3, Name = "model3", Class = "C", },                            
        new MyModel() { ID = 4, Name = "model4", Class = "D", },
        new MyModel() { ID = 5, Name = "model5", Class = "E", },            
};

//A. This code assigns null for unknown IDs
//I.e. if (ID > 0 && ID < colorPallete.Length) then color will be picked from colorPallete[],
//else it will be null
list.ForEach(x => x.Color = colorPallete.ElementAtOrDefault(x.ID - 1));

//B. This code apply some default color for unknown IDs
//I.e. if (ID > 0 && ID < colorPallete.Length) then color will be picked from colorPallete,
//else it will be "DefaultColor"
list.ForEach(x => x.Color = colorPallete.ElementAtOrDefault(x.ID - 1) ?? "DefaultColor");

//C. This code can assign the same color to models with different IDs, 
//but models with identical IDs always will have identical color
list.ForEach(x => x.Color = colorPallete.ElementAtOrDefault((x.ID - 1) % colorPallete.Length));

Upvotes: 0

Enigmativity
Enigmativity

Reputation: 117019

This works for me:

var colorPallete = new string[]
{
    "color1", "color2", "color3", "color4", "color5",
};

var previousList = new []
{
    new { ID = 1, Name = "abc", Class = "Senior", },
    new { ID = 2, Name = "xyz", Class = "Medium", },
    new { ID = 3, Name = "pqr", Class = "junior", },
    new { ID = 1, Name = "mno", Class = "junior", },
};

var newList =
    previousList
        .Select(x => new
        {
            x.ID,
            x.Name,
            x.Class,
            Color = colorPallete.ElementAtOrDefault(x.ID - 1),
        })
        .ToList();

I get this result:

result


With the question update providing the class MyModel the code can then be written like so:

var colorPallete = new string[]
{
    "color1", "color2", "color3", "color4", "color5",
};

var previousList = new List<MyModel>()
{
    new MyModel() { ID = 1, Name = "abc", Class = "Senior", },
    new MyModel() { ID = 2, Name = "xyz", Class = "Medium", },
    new MyModel() { ID = 3, Name = "pqr", Class = "junior", },
    new MyModel() { ID = 1, Name = "mno", Class = "junior", },
};

var newList =
    previousList
        .Select(x => new MyModel()
        {
            ID = x.ID,
            Name = x.Name,
            Class = x.Class,
            Color = colorPallete.ElementAtOrDefault(x.ID - 1),
        })
        .ToList();

Which gives:

MyModel result

Now, this approach produces a new list keeping the old list and the old objects intact. Generally this is what you should try to do. It's best to mutate objects only when you know that's what they're designed to do.

So it becomes possible to do an in-place update of the original list like so:

previousList.ForEach(x => x.Color = colorPallete.ElementAtOrDefault(x.ID - 1));

This results in modifying the previousList objects without creating a newList.

Upvotes: 3

diiN__________
diiN__________

Reputation: 7656

I would create a class for the objects with a color property like this:

public class MyClass
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Class { get; set; }
    public string Color { get; set; } // Nullable
}

And for the colors I would create another class with an ID to compare with the ID of MyClass:

public class MyColor
{
    public int ID { get; set; }
    public string Color { get; set; }
}

For each color in colorPalette you would assign an ID that matches the ID of the list of MyClass.

So at first the color from MyClass would be null. And then you could loop over the list of MyClass:

foreach (MyClass myClass in myClassList)
{
    myClass.Color = colorPalette.FirstOrDefault(col => col.ID = myClass.ID);
}

Or without an ID in Color class (comparing the names of the variables which is not a beautiful solution):

foreach (MyClass myClass in myClassList)
{
    myClass.Color = colorPalette.FirstOrDefault(col => int.Parse(nameof(col.Color).Replace("color", "")) == myClass.ID);
}

Upvotes: 0

Related Questions