【问题标题】:create a table that displays the object hierarchy from a JSON object创建一个显示 JSON 对象的对象层次结构的表
【发布时间】:2020-01-17 02:48:56
【问题描述】:

我有以下对象:

let data = {
  A: {
    B1: {
      C1: {
        D1: "foo"
      },
      C2: {
        D2: "bar",
        D3: "baz"
      }
    },
    B2: {
      C3: {
        D4: "qux"
      },
      C4: {
        D5: "quux"
      }
    }
  }
};

我想创建一个函数来创建一个表格,在类似“桑基图”的视图中显示嵌套结构:

【问题讨论】:

    标签: javascript json html-table


    【解决方案1】:

    我将我的解决方案分解成一些伪代码:

    get_table(data):
      # Map resulting rows with "tr" elements
      return recurse_dataset.map(row => "<tr>row</tr>")
    
    # Return list of rows (only "td" elements)
    recurse_dataset(data):
      if data is root:
        return data
      else:
        # Get all child rows and add to a result
        result = []
        for key, value in data:
          roots = number_roots(value)
          # Recurse further into object to get root rows
          for index, row in recurse_dataset(value):
            # If we are the first result and we have children,
            #   add our key cell with overlap
            if index == 0 and roots > 0:
              row = "<td rowspan=roots>key</td>" + row
            result += row
        return result
    
    number_roots(data):
      if data is root:
        return 1
      else:
        count = 0
        for value in data:
          count += number_roots(value)
        return count
    

    或者,在一个 sn-p 中:

    const getTable = function(data) {
      return getRows(data).map(row => `<tr>${row}</tr>`).join("");
    };
    
    const getRows = function(data) {
      if(typeof data !== "object") {
        return [
          `<td>${data}</td>`
        ];
      }
      else {
        let result = [];
        for(let [key, value] of Object.entries(data)) {
          let children = getChildrenCount(value);
          let rows = getRows(value);
          rows.forEach((row, index) => {
            if(index == 0 && children) {
              row = `<td rowspan="${children}">${key}</td>
    ${row}`;
            }
            result.push(row);
          });
        };
        return result;
      }
    };
    
    const getChildrenCount = function(data) {
      if(typeof data !== "object") {
        return 1;
      }
      else {
        let count = 0;
        for(let [key, value] of Object.entries(data)) {
          count += getChildrenCount(value);
        };
        return count;
      }
    };
    
    let data = {
      A: {
        B1: {
          C1: {
            D1: "foo"
          },
          C2: {
            D2: "bar",
            D3: "baz"
          }
        },
        B2: {
          C3: {
            D4: "qux"
          },
          C4: {
            D5: "quux"
          }
        }
      }
    };
    
    $("tbody").append(getTable(data));
    table td,
    table th {
        min-width: 2em;
        min-height: 2em;
        border: 1px solid #000;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <table>
      <tbody></tbody>
    </table>

    如果你想要一个“摘要”行来显示每个组中有多少元素:

    const getTable = function(data) {
      return getRows(data).map(row => `<tr>${row}</tr>`).join("");
    };
    
    const getRows = function(data) {
      if(typeof data !== "object") {
        return [
          `<td>${data}</td>`
        ];
      } 
      else {
        let result = [];
        for(let [key, value] of Object.entries(data)) {
          let children = getChildrenCount(value);
          let depth = getDepth(value);
          let rows = getRows(value);
          rows.forEach((row, index) => {
            if(index == 0 && children) {
            	result.push(`<td rowspan="${children + getExtraSpan(value)}">${key}</td>${row}`);
            }
            else {
            	result.push(row);
            }
          });
          if(depth) {
            result.push(`<td ${depth ? `colspan="${depth}"` : ""}>Count</td><td>${children}</td>`);
          }
        };
        return result;
      }
    };
    
    const getDepth = function(data) {
      if(typeof data !== "object") {
        return 0;
      }
      else {
        let count = 0;
        for(let [key, value] of Object.entries(data)) {
          count = Math.max(count, getDepth(value));
        };
        return count + 1;
      }
    };
    
    const getChildrenCount = function(data) {
      if(typeof data !== "object") {
        return 1;
      } 
      else {
        let count = 0;
        for(let [key, value] of Object.entries(data)) {
          count += getChildrenCount(value);
        };
        return count;
      }
    };
    
    const getExtraSpan = function(data) {
      if(typeof data !== "object") {
        return 0;
      } 
      else {
        let count = getDepth(data) ? 1 : 0;
        for(let [key, value] of Object.entries(data)) {
          count += getExtraSpan(value);
        };
        return count;
      }
    }
    
    let data = {
      A: {
        B1: {
          C1: {
            D1: "foo"
          },
          C2: {
            D2: "bar",
            D3: "baz"
          }
        },
        B2: {
          C3: {
            D4: "qux"
          },
          C4: {
            D5: "quux"
          }
        }
      }
    };
    
    $("tbody").append(getTable(data));
    table td,
    table th {
      min-width: 2em;
      min-height: 2em;
      border: 1px solid #000;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <table>
      <tbody></tbody>
    </table>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-17
      • 1970-01-01
      相关资源
      最近更新 更多