using System.Collections.Generic;
public class RegionCategoryDto
public string Id { get; set; }
public string Name { get; set; }
public string TypeId { get; set; }
public string ParentId { get; set; }
public class RegionCategoryGraphType
public string Id { get; set; }
public string Name { get; set; }
public RegionCategoryType CategoryType { get; set; }
public string ParentId { get; set; }
public string RegionName { get; set; }
public string MarketName { get; set; }
public bool IsAuthorizedToCurrentUser { get; set; }
public bool IsPrimary { get; set; }
public List<RegionCategoryGraphType> Children { get; set; } = new List<RegionCategoryGraphType>();
public enum RegionCategoryType
public static List<RegionCategoryGraphType> BuildTree(List<RegionCategoryDto> dtos)
var lookup = dtos.ToDictionary(dto => dto.Id, dto => new RegionCategoryGraphType
CategoryType = MapCategoryType(dto.TypeId),
var rootNodes = new List<RegionCategoryGraphType>();
foreach (var node in lookup.Values)
if (string.IsNullOrEmpty(node.ParentId) || !lookup.ContainsKey(node.ParentId))
var parent = lookup[node.ParentId];
parent.Children.Add(node);
private static RegionCategoryType MapCategoryType(string typeId)
"1" => RegionCategoryType.Region,
"2" => RegionCategoryType.Market,
"3" => RegionCategoryType.Group,
_ => RegionCategoryType.Unknown
public static void Main()
var dtos = new List<RegionCategoryDto>
new RegionCategoryDto { Id = "1", Name = "Southwesd", TypeId = "1", ParentId = null },
new RegionCategoryDto { Id = "2", Name = "Denver", TypeId = "2", ParentId = "1" },
new RegionCategoryDto { Id = "3", Name = "Denver South", TypeId = "3", ParentId = "2" },
new RegionCategoryDto { Id = "4", Name = "Northeast", TypeId = "1", ParentId = null },
new RegionCategoryDto { Id = "5", Name = "Boston North", TypeId = "2", ParentId = "4" }
var tree = TreeBuilder.BuildTree(dtos);
Console.WriteLine(JsonConvert.SerializeObject(tree));
private static void PrintTree(List<RegionCategoryGraphType> nodes, int level)
foreach (var node in nodes)
Console.WriteLine(new string('-', level * 2) + node.Name);
PrintTree(node.Children, level + 1);