Code_Learner21
Code_Learner21

Reputation: 17

How do I loop through an array and add each value to my model variable? MVC Razor

I am trying to make a variable in my model that retrieves all available skills to later display them in a DDL. I have one variable that contains all of the skills and one variable that displays all of the skills an employee has already rated. I want to check all of the skills against the rated skills so that only the unrated skills are added to the new variable in the model. The only way I could think of to do this is to use a foreach loop to check for the values in the AllSkills variable.

model:

public IEnumerable<long> AvailableSkills { get; set; }
public IEnumerable<long> AllSkills { get; set; }
public IEnumerable <long> EmployeeRatings { get; set; }          
public IEnumerable<Rating> Ratings { get; set; }
public IEnumerable<Skill> Skills { get; set; }
public long SkillId { get; set; }

Controller:

model.AllSkills = db.Skills.OrderBy(s => s.SkillName).Select(s => s.SkillId);
model.EmployeeRatings = db.Ratings.Where(r => r.EmployeeId == User.Identity.Name.Remove(0, 8)).OrderBy(s => s.SkillId).Distinct();

foreach (var skill in model.EmployeeRatings)
        {
            model.AvailableSkills = model.AllSkills.Where(s => s != skill);
        }

I want to do something like the following code in the foreach loop:

model.AvailableSkills += model.AllSkills.Where(s=> s != skill); but this is not allowed.

The problem is that this for each loop above is assigning the model.AvailableSkills to the every skill but the last one that is in the foreach loop (as it should). How do I make it so that every one of the duplicate skills are excluded from model.AvailableSkills?

Upvotes: 0

Views: 1442

Answers (4)

Ric .Net
Ric .Net

Reputation: 5540

Using LINQ is IMO more readable if you use to query syntax opposed to the method chaining syntax.

model.AllSkills = 
   from skill in db.Skills
   orderby skill.SkillName
   select skill.SkillId;

model.EmployeeRatings = 
     from rating in db.Ratings
     let employeeId = User.Identity.Name.Remove(0, 8)
     where rating.EmployeeId == employeeId
     orderby rating.SkillId
     select rating.SkillId

You can use the Except() extension method to remove items from the collection.

// exclude the 'owned' skils
model.AvailableSkills = model.AllSkills.Except(model.EmployeeRatings);

And you probably want to distinct the results:

model.AvailableSkills = model.AvailableSkills.Distinct(); 

Last but not least: Because you select the SkillId I'm unsure why you would order the results. This does not make sense especially because you order by different properties in both lists. Furtermore you probably want to select more details to display to the user, but to know this we need more details on your model.

Upvotes: 1

lintmouse
lintmouse

Reputation: 5119

Following your current approach, you can use AddRange with a list. Something like:

List<long> availableSkills = new List<long>();

foreach (var skill in model.EmployeeRatings)
{
    availableSkills.AddRange(model.AllSkills.Where(s => s != skill));
}

model.AvailableSkills = availableSkills;

Or you can achieve this with a more compact approach, and I believe Except removes dupes:

model.AvailableSkills = model.AllSkills.Except(model.EmployeeRatings);

Upvotes: 0

brroshan
brroshan

Reputation: 1650

Consider two classes like this:

public class Skill
{
    public int Id { get; set; }
}

public class Employee
{
    public int[] RatedSkills { get; set; }
}

var skills = new List<Skill>
        {
            new Skill{ Id = 1}, new Skill{Id = 2}, new Skill{ Id = 3}, new Skill { Id = 4}
        };

        var emp = new Employee
        {
            RatedSkills = new int[] { 1,2 }
        };

        var availableSkills = skills.Select(s => s.Id).Except(emp.RatedSkills);

        Console.Read();

The rating has an Id property an an employee has an int[] to hold his/her selected ratings. From there it's easy to filter

Upvotes: 0

Frank Fajardo
Frank Fajardo

Reputation: 7359

Assuming EmployeeRatings contains rated skills, and you want AvailableSkills to have only skills not in EmployeeRatings but are in AllSkills, I think this is what you like to do:

model.AvailableSkills = model.AllSkills
     .Where(s => !model.EmployeeRatings.Contains(s));

Upvotes: 0

Related Questions