Find two values in hierarchical object tree C# using Linq

Viewed 42

I have the following structures:

using System.Collections.Generic;

public class Program
{

    public static void Main() 
    {
        var tourn = new Tournament();
        var player = new Player() { Type = PlayerType.User };
        var seat1 = new Seat() { Number = 1, Player = player } ;
        tourn.Tables = new List<Table>() { new Table(){ Seats = new List<Seat>(){seat1} } };
        
        //Console.WriteLine(tourn.Tables.Where((k=> k.Tables.Any(m=> m.Seats.Any(j=> j.Player == Player.User)))).Count());
        
        // Get Table and Seat numbers for PlayerType.User
    }

    public class Seat{
        public Player? Player {get;set;}    
        public int Number {get;set;}
    }
    
    public enum PlayerType {
        User,
        Bot
    }

    public class Tournament{
        public List<Table> Tables {get;set;}
    }
    
    public class Table
    {
        public List<Seat> Seats {get;set;}  
        public int Number {get;set;}
    }
    
    public class Player
    {
        public PlayerType Type { get; set; }
    }
}

I have want the table and seat number where the playertype = user

Is it possible to build a Linq query to do this in one statement?

(I have looked at many examples and can't seem to get it right)

Tried this:

var playerLocation = tables
    .Select(seat => new
    {
        TableNumber = seat.TableNumber,
        TableSeat = seat.Seats
            .Where(s => s.Player is not null &&
                   s.Player.Type == PlayerType.User)
            .Select(st => new
            {
                SeatNumber = st.Number
            })
        });

Fiddle (.NET Core): https://dotnetfiddle.net/CMjZs6

3 Answers

I cheated...

                PlayerLocation location = new PlayerLocation();

                foreach (Table table in tables)
                    foreach (Seat seat in table.Seats)
                        if (seat.Player is not null && seat.Player.Type == PlayerType.User)
                        {
                            location.TableNumber = table.TableNumber;
                            location.SeatNumber = seat.Number;
                            break;
                        }

Assuming you want the answer as an object with the table number and a list of seat numbers, it is straightforward:

var ans = tourn.Tables.Select(t => new {
    t.Number,
    Seats = t.Seats.Where(s => s.Player?.Type == PlayerType.User)
                   .Select(s => s.Number)
                   .ToList()
});

Based On your Updated Fiddle

    var anonyType = tourn.Tables.Where(k=> k.Seats.Any(j=> j.Player?.Type == PlayerType.User)).Select(k=> new { TableNumber = k.Number, SeatNumbers = k.Seats.Select(j=> j.Number) }).FirstOrDefault();
    Console.WriteLine(anonyType.TableNumber);
    Console.WriteLine(String.Join(" , ", anonyType.SeatNumbers));
Related