c# - 递归列表到格式良好的表
问题描述
我遇到了一个稍微复杂的问题,我发现很难解决。
我有一堂课:
public class Location
{
public string Name { get; set; }
public List<Location> ChildLocations { get; set; }
}
它再次引用了 Child Location 对象。所以这是一个递归列表,我想在格式良好的 HTML 表中输出这个列表。这是代码:
using System.Collections.Generic;
using System.Web.Mvc;
namespace WebApplication1.Controllers
{
public class Location
{
public string Name { get; set; }
public List<Location> ChildLocations { get; set; }
}
public class HomeController : Controller
{
public ActionResult Index()
{
List<Location> locations = new List<Location>() {
new Location() {
Name = "Item 1",
ChildLocations = new List<Location>() {
new Location()
{
Name="Female",
ChildLocations = new List<Location>()
{
new Location() { Name = "Female 1" },
new Location() { Name = "Female 2" }
}
},
new Location()
{
Name="Male",
ChildLocations = new List<Location>()
{
new Location() { Name = "Male 1" },
new Location() { Name = "Male 2" }
}
}
}
},
new Location() {
Name = "Item 2",
ChildLocations = new List<Location>() {
new Location()
{
Name="Female",
ChildLocations = new List<Location>()
{
new Location() { Name = "M1" },
new Location() { Name = "M2" },
new Location() { Name = "M3" }
}
},
new Location()
{
Name="Male",
ChildLocations = new List<Location>()
},
new Location()
{
Name="Unknown",
ChildLocations = new List<Location>()
}
}
}
};
return View(locations);
}
}
}
我想让输出看起来像这样:
<table class="table table-border">
<tr>
<td rowspan="4">
Item 1
</td>
<td rowspan="2">
Female
</td>
<td>
Female 1
</td>
</tr>
<tr>
<td>Female 2</td>
</tr>
<tr>
<td rowspan="2">Male</td>
<td>Male 1</td>
</tr>
<tr>
<td>Male 2</td>
</tr>
<tr>
<td rowspan="5">
Item 2
</td>
<td rowspan="3">Female</td>
<td>M1</td>
</tr>
<tr>
<td>M2</td>
</tr>
<tr>
<td>
M3
</td>
</tr>
<tr>
<td>Male</td>
</tr>
<tr>
<td>Unknown</td>
</tr>
</table>
如果有人想查看 HTML,我有 jsfiddle:
https://jsfiddle.net/4pk0necp/
我想使用我在cshtml中以语法方式编写的数据来呈现这种类型的表:
@using WebApplication1.Controllers;
@model List<Location>
@{
ViewBag.Title = "Home Page";
}
我知道需要一个计算行跨度的函数,所以我创建了这个正确返回深度的小函数:
public static int GetDepth(this Location location)
{
int noOfchildren = 0;
bool counted = false;
foreach (Location item in location.ChildLocations)
{
if (item.ChildLocations.Count <= 0)
{
if (!counted)
{
noOfchildren += location.ChildLocations.Where(i => i.ChildLocations.Count <= 0).Count();
counted = true;
}
}
else
noOfchildren += GetDepth(item);
}
return noOfchildren;
}
Tree about 的给出列表只是一个示例,树中可以有多个深度级别。任何帮助表示赞赏。
编辑:我调整了我的 GetDepth 函数,因为我们只需要叶级节点数。
解决方案
尝试使用以下类。仅勉强测试:
public class TreeDrawer {
private readonly Dictionary<Location, int> _depthMap;
public TreeDrawer() {
_depthMap = new Dictionary<Location, int>();
}
public string Draw(IEnumerable<Location> locations) {
var sb = new StringBuilder("<table>");
bool first = true;
foreach (var l in locations) {
Draw(l, sb, true, first);
first = false;
}
sb.Append("</table>");
return sb.ToString();
}
private void Draw(Location l, StringBuilder sb, bool fromRoot, bool first) {
int depth = GetDepth(l);
bool openedRow = false;
if (fromRoot || !first) {
sb.Append("<tr>");
openedRow = true;
}
sb.Append("<td");
if (depth > 1) {
sb.Append(" rowspan=\"");
sb.Append(depth);
sb.Append("\"");
}
sb.Append(">");
sb.Append(l.Name);
sb.Append("</td>");
bool isFirstChild = true;
if (l.ChildLocations != null) {
foreach (var child in l.ChildLocations) {
Draw(child, sb, false, isFirstChild);
isFirstChild = false;
}
}
if (openedRow) {
sb.Append("</tr>");
}
}
private int GetDepth(Location l) {
if (!_depthMap.ContainsKey(l)) {
_depthMap.Add(l, Math.Max(1, l.ChildLocations?.Sum(GetDepth) ?? 0));
}
return _depthMap[l];
}
}
推荐阅读
- java - 为 Json 数组创建映射类
- python - 从 sql 字符串中提取表名、列等参数
- python - 如何从文本中解析参数?
- xcode - Xcode 10.2 不是为 ios 12.3 beta 1 构建的
- junit - 如何在集成测试中一起使用这些 @DataMongoTest 和 @SpringBootTest
- c++ - 什么是符号`myLibrary!__scrt_stub_for_is_c_termination_complete+0x12345`
- jquery - 为什么悬停功能不起作用?(jQuery)
- angular - 如何在 Mat Table 中添加一列 - Angular?
- bixby - capsule.bxb 中的警告信息
- r - 将组合的逗号和冒号分隔变量传播到单独的逻辑列中