Search code examples
apilinqasynchronousasync-awaitentity-framework-core

How to return a List from nested lists with LINQ?


I have to return all rooms which doesn't contain Cat or Owl. If a room contains even one forbidden animal, it cannot be added to the list which we'd like to return. It's going to be a method for a service which is used as an API endpoint.

public async Task<List<Room>> GetRoomForRabbitOwners() 
{
}
public enum PetType : byte
{
        Cat,
        None,
        Rabbit,
        Owl
}

Here is the data structure :

[
    {
        "id": 1,
        "capacity": 5,
        "residents": [
            {
                "id": 2,
                "name": "Tom",
                "houseType": 2,
                "petType": 1,
                "room": null
            },
            {
                "id": 4,
                "name": "Nicol",
                "houseType": 2,
                "petType": 3,
                "room": null
            }
        ]
    },
    {
        "id": 2,
        "capacity": 5,
        "residents": [
            {
                "id": 3,
                "name": "Rambo",
                "houseType": 2,
                "petType": 2,
                "room": null
            }
        ]
    },
    {
        "id": 3,
        "capacity": 1010,
        "residents": []
    },
    {
        "id": 4,
        "capacity": 10,
        "residents": []
    },
    {
        "id": 5,
        "capacity": 15,
        "residents": []
    }
]

A bunch of times, I managed to write an expression which seemed good but in the end it failed by returning a List of "Tenant" (class) , since only "Room" (class) allowed.


Solution

  • It seems like your post needs a little more information. I.e. what do you mean with tenant vs resident? Also your data structure defines a room as containing residents. Do you want the room returned w/out it's residents?

    Here's a solution that returns a list of rooms w/out Cats & Owls:

    void Main()
    {
        var data = File.ReadAllText(Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.Desktop), 
            "data.json"));
        
        var allRooms = JsonConvert.DeserializeObject<List<Room>>(data);
    
        var filteredRooms = GetRoomForRabbitOwners(allRooms).Dump();
    }
    
    public List<Room> GetRoomForRabbitOwners(List<Room> rooms)
    {
        return rooms
            .Where(room => !room.Residents.Any(resident =>
                (PetType)resident.PetType == PetType.Cat ||
                (PetType)resident.PetType == PetType.Owl))      
            .ToList();
    }
    
    public enum PetType : byte
    {
        Cat = 1,
        None = 2,
        Rabbit = 3,
        Owl = 4
    }
    
    public class Resident
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int HouseType { get; set; }
        public byte PetType { get; set; }
        public int? Room { get; set; }
    }
    
    public class Room
    {
        public int Id { get; set; }
        public int Capacity { get; set; }
        public List<Resident> Residents { get; set; }
    }