Search code examples
c#listdropdown

Remove the same values when comparing multiple lists


I have 3 people living in 3 houses.

  • Person A (Joe) lives in house 1.
  • Person B (Jane) lives in house 2.
  • Person C (Max) lives in house 3.

I have a button with which I make an assignment for certain persons. It becomes a kind of user administration. E.g. person A has the permission to enter house C.

I would like to be able to display only the houses that have not been assigned yet.

Illustrated as follows:

  • Joe is the owner of house A and caretaker of house B.

If I want to assign him a new role now (caretaker of house C), I want only house C (the only unassigned house) to be displayed in the dropdown list.

enter image description here

Problem: Currently all houses are displayed.

Code structure:

I can create a new person or edit an existing person. I have an enum class for role assignment:

public enum RoleType
{
    [Display(Name = "Owner")]
    Owner = 0,

    [Display(Name = "Janitor")]
    Janitor = 1
}

I also have a model for role definition:

public class RoleDefinitionModel
{
    private RoleType? _role;
    private House _selectedHouse;
    
    public RoleDefinitionModel(IList<House> availableHouse, RoleType? selectedRole, House selectedHouse)
    {
        AvailableHouses = availableHouse;
        _role = selectedRole;
        _selectedHouse = selectedHouse;
        StartChangeTracking();
    }
    
    public virtual RoleType? SelectedRole
    {
        get { return _role; }
        set
        {
            if (_role == value)
                return;
            _role = value;
            NotifyChanges();
        }
    }
    
    public virtual House SelectedHouse
    {
        get { return _selectedHouse; }

        set
        {
            if (_selectedHouse == value)
                return;
            _selectedHouse = value;
            NotifyChanges();
        }
    }
    
    public virtual IList<House> AvailableHouses { get; }

    public virtual IList<RoleType> AvailableRoles { get; } = Enum<RoleType>.GetValues().ToList();
}

I already have an add and remove method, which also work. There is only one problem: When I click on the button I get my desired dropdown. But I can select all houses. And I only want to see the houses to which I have not been assigned a role yet.

public virtual void AddRoleDefinition()
{
    var roleDefinition = new RoleDefinitionModel(House, null, null);
    _roleDefinitions.Add(roleDefinition);
    this.SubscribeChanged(roleDefinition);
}

Which is the most effective way to check it:

  • Where() and Any() from System.Linq:

_roleDefinitions.Where(....Any());

  • Contains()

  • or Remove() in a foreach-loop?

for (var i = selectedHouse.Count - 1; i >= 0; --i)
{
    if (availableHouses.Contains(selectedHouse[i].Uid))
    {
        availableHouses.Remove(selectedHouse[i]);
    }
}

foreach (var selectedhouse in availableHouses)
{
    ...
}

However, I think this approach is wrong and my queries are wrong here. How can I resolve this?


Solution

  • Can you not add a property to your House object such as :

    public House()
    {
       ...
       public bool HasBeenAssigned
       {
         get;
         set;
       }
    }
    

    Then use LINQ in order to select only those House objects that have not been assigned yet

    public List<House> AvailableHouses 
    { 
      return ListOFHouses.Where(house => !house.HasBeenAssigned).Select(item => item).toList();
    }
    

    In regards to which method to adopt I would suggest - as per its use in my answer LINQ.

    There is nothing wrong with the foreach loop - however as you can see the LINQ statement is more readable, maintainable, elegant and its shows intend.

    The use of Where clause would be more appropriate in this case - we are looking in the list of house where the value of HasBeenAssigned is false. This will return a list on enumerable which we select and we cast as a list.

    We are not interested if there are any which implies a boolean result. In fact the Any clause will return a boolean list.