【问题标题】:Building a family tree from an array of objects从对象数组构建家谱
【发布时间】:2018-07-18 02:00:35
【问题描述】:

我正在尝试从 javascript 中的对象数组构建家谱。 数据存储在 MySQL 数据库中,并通过 PHP 页面访问。

我将一组对象从 PHP 返回到 javascript,如下所示: (基本上就是所有的条目)

0 : {id: 24, sheep_name: "Mick", dam: 17, sire: 16}
1 : {id: 25, sheep_name: "Wendy", dam: 17, sire: 16}
2 : {id: 26, sheep_name: "Will", dam: 0, sire: 0}
3 : {id: 27, sheep_name: "a", dam: 25, sire: 26}
4 : {id: 28, sheep_name: "b", dam: 25, sire: 26}
5 : {id: 29, sheep_name: "c", dam: 25, sire: 26}
6 : {id: 30, sheep_name: "d", dam: 25, sire: 26}
7 : {id: 23, sheep_name: "h", dam: 19, sire: 18}
8 : {id: 21, sheep_name: "f", dam: 19, sire: 18}
9 : {id: 19, sheep_name: "Karen", dam: 0, sire: 0}
10 : {id: 20, sheep_name: "e", dam: 19, sire: 18}
11 : {id: 16, sheep_name: "Bob", dam: 0, sire: 0}
12 : {id: 17, sheep_name: "Stella", dam: 0, sire: 0}
13 : {id: 18, sheep_name: "Joe", dam: 17, sire: 16}
14 : {id: 22, sheep_name: "g", dam: 19, sire: 18}

最终目的是生成如下 HTML 列表:

<ul>
    <li>a [27]
        <ul>
            <li>Wendy [25]
                <ul>
                    <li>Stella [17]</li>
                    <li>Bob [16]</li>
                </ul>
            </li>
            <li>Will [26]</li>
        </ul>
    </li>
</ul>

那么,给定一个起点 - id: 27 -sheep_name: 'a',我如何着手生成数据来创建列表?

我知道我将不得不多次循环遍历数据,直到没有返回任何结果,但它的机制对我来说已经丢失了。

数据集不固定,可以随时添加父母和孩子。

我可以完全控制这方面的所有方面,javascript、PHP 和 MySQL,包括数据库结构。

任何指点或建议都非常感谢...

作为参考,这是羊的家谱,“起点”是一个孩子,然后家谱:

父母 - 祖父母 = 曾祖父母 - 曾曾祖父母 - 等等。

这就像人类的家谱,但相反。

*注:Dam = 母亲,Sire = 父亲

【问题讨论】:

  • 如果这只是一个学术项目,那么这种结构将起作用。如果您正在尝试建立实际的家谱,那么这绝对是不够的。在这种情况下,您需要一个更通用的图结构,因为事情会变得非常疯狂。
  • 第一个提示:如果您递归执行,这将容易得多。第二个提示:您需要一种使查找变得容易的数据结构:普通对象或以 id 为键的 Map。
  • 你需要想想你想对拥有相同父母的兄弟姐妹做什么......这将如何呈现?

标签: javascript php mysql arrays object


【解决方案1】:

这是一个简单的递归函数,可以创建一个您可以使用的 html 字符串:

var sheep = [
{id: 24, sheep_name: "Mick", dam: 17, sire: 16},
{id: 25, sheep_name: "Wendy", dam: 17, sire: 16},
{id: 26, sheep_name: "Will", dam: 0, sire: 0},
{id: 27, sheep_name: "a", dam: 25, sire: 26},
{id: 28, sheep_name: "b", dam: 25, sire: 26},
{id: 29, sheep_name: "c", dam: 25, sire: 26},
{id: 30, sheep_name: "d", dam: 25, sire: 26},
{id: 23, sheep_name: "h", dam: 19, sire: 18},
{id: 21, sheep_name: "f", dam: 19, sire: 18},
{id: 19, sheep_name: "Karen", dam: 0, sire: 0},
{id: 20, sheep_name: "e", dam: 19, sire: 18},
{id: 16, sheep_name: "Bob", dam: 0, sire: 0},
{id: 17, sheep_name: "Stella", dam: 0, sire: 0},
{id: 18, sheep_name: "Joe", dam: 17, sire: 16},
{id: 22, sheep_name: "g", dam: 19, sire: 18}
];

function createSheepHTML(id) {
  var s = sheep.find(e => e.id == id);
  if (s) {
    var out = "<li>" + s.sheep_name + " [" + s.id + "]";
    if (s.dam || s.sire) {
      out += "<ul>";
      if (s.dam) {
        out += createSheepHTML(s.dam);
      }
      if (s.sire) {
        out += createSheepHTML(s.sire);
      }
      out += "</ul>";
    }
    out += "</li>";
    return out;
  }
}

document.getElementById("sheepGoHere").innerHTML = createSheepHTML(27);
    
&lt;ul id="sheepGoHere"&gt;&lt;/ul&gt;

【讨论】:

    【解决方案2】:

    您可以获取一个包含所有对父母的引用的对象,然后选择该人的id 并获取嵌套对象。

    var family = [{ id: 24, sheep_name: "Mick", dam: 17, sire: 16 }, { id: 25, sheep_name: "Wendy", dam: 17, sire: 16 }, { id: 26, sheep_name: "Will", dam: 0, sire: 0 }, { id: 27, sheep_name: "a", dam: 25, sire: 26 }, { id: 28, sheep_name: "b", dam: 25, sire: 26 }, { id: 29, sheep_name: "c", dam: 25, sire: 26 }, { id: 30, sheep_name: "d", dam: 25, sire: 26 }, { id: 23, sheep_name: "h", dam: 19, sire: 18 }, { id: 21, sheep_name: "f", dam: 19, sire: 18 }, { id: 19, sheep_name: "Karen", dam: 0, sire: 0 }, { id: 20, sheep_name: "e", dam: 19, sire: 18 }, { id: 16, sheep_name: "Bob", dam: 0, sire: 0 }, { id: 17, sheep_name: "Stella", dam: 0, sire: 0 }, { id: 18, sheep_name: "Joe", dam: 17, sire: 16 }, { id: 22, sheep_name: "g", dam: 19, sire: 18 }],
        ids = {};
    
    family.forEach(function (person) {
        ids[person.id] = Object.assign(ids[person.id] || {}, person);
        ids[person.dam] = ids[person.dam] || {};
        ids[person.id].dam = ids[person.dam];
        ids[person.sire] = ids[person.sire] || {};
        ids[person.id].sire = ids[person.sire];
    });
    
    console.log(JSON.stringify(ids, 0, 4));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      【解决方案3】:

      我会首先在 ES6 Map 中通过对象的 id 来键入对象。然后使用递归函数:

      • 在地图中查找给定的 id 以检索具有该/那些 id 的对象
      • 跳过 id 不匹配的那些(比如 0)
      • 使用递归为每个对象的父亲和母亲构建 HTML,并将该对象的 HTML 与当前对象的信息一起包装在 li 标记中
      • 将这些 HTML 连接在一起并将结果包装在 ul 标记中

      作为可选添加,您可以传递缩进级别。

      这是 ES6 代码:

      function toHTML(sheep, id) {
          return (function recurse(map, ids, indent) {
              const html = ids.map( id => map.get(id) ) // Retrieve the sheep objects by id
                  .filter(Boolean) // Remove non-matches
                  .map(obj => `${indent}  <li>${obj.sheep_name} [${obj.id}]\n` +
                              recurse(map, [obj.dam, obj.sire], indent+'    ') + // Recurse
                              `${indent}  </li>\n`)
                  .join('');
              return html.length ? `${indent}<ul>\n${html}${indent}</ul>\n` : '';
          })(new Map(sheep.map(obj => [obj.id, obj])), [id], ''); // Create map
      }
      
      const sheep = [{id: 24, sheep_name: "Mick", dam: 17, sire: 16},{id: 25, sheep_name: "Wendy", dam: 17, sire: 16},{id: 26, sheep_name: "Will", dam: 0, sire: 0},{id: 27, sheep_name: "a", dam: 25, sire: 26},{id: 28, sheep_name: "b", dam: 25, sire: 26},{id: 29, sheep_name: "c", dam: 25, sire: 26},{id: 30, sheep_name: "d", dam: 25, sire: 26},{id: 23, sheep_name: "h", dam: 19, sire: 18},{id: 21, sheep_name: "f", dam: 19, sire: 18},{id: 19, sheep_name: "Karen", dam: 0, sire: 0},{id: 20, sheep_name: "e", dam: 19, sire: 18},{id: 16, sheep_name: "Bob", dam: 0, sire: 0},{id: 17, sheep_name: "Stella", dam: 0, sire: 0},{id: 18, sheep_name: "Joe", dam: 17, sire: 16},{id: 22, sheep_name: "g", dam: 19, sire: 18}];
      const html = toHTML(sheep, 27);
      console.log(html);
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-19
        • 2023-03-24
        • 2018-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-08
        相关资源
        最近更新 更多