Coder Social home page Coder Social logo

tree's Introduction

Overview

This library provides handling of data that is structured hierarchically using parent ID references. A typical example is a table in a relational database where each record’s “parent” field references the primary key of another record. Of course, usage is not limited to data originating from a database, but anything: you supply the data, and the library uses it, regardless of where the data came from and how it was processed.

It is important to know that the tree structure created by this package is read-only: you can’t use it to perform modifications of the tree nodes.

On the other hand, one nice thing is that it’s pretty fast. This does not only mean the code itself, but also that the constructor takes the input data in a format that is simple to create. For instance, to create a tree from database content, a single SELECT is sufficient, regardless of the depth of the tree and even for thousands of nodes.

Installation

The preferred way to install Tree is through Composer. For this, simply execute composer require bluem/tree (depending on your Composer installation, it could be “composer.phar” instead of “composer”) and everything should work fine. Or you manually add "bluem/tree": "^3.0" to the dependencies in your composer.json file and subsequently install/update dependencies.

Alternatively, you can clone the repository using git or download a tagged release.

Updating

As this library uses semantic versioning, you will get fixes and feature additions when running composer update, but not changes which break the API.

Usage

Creating a tree

// Create the tree with an array of arrays (or use an array of Iterators,
// Traversable of arrays or Traversable of Iterators):
$data = [
    ['id' => 1, 'parent' => 0, 'title' => 'Node 1'],
    ['id' => 2, 'parent' => 1, 'title' => 'Node 1.1'],
    ['id' => 3, 'parent' => 0, 'title' => 'Node 3'],
    ['id' => 4, 'parent' => 1, 'title' => 'Node 1.2'],
];
$tree = new BlueM\Tree($data);

// When using a data source that uses different keys for "id" and "parent",
// or if the root node ID is not 0 (in this example: -1), use the options
// array you can pass to the constructor:
$data = [
    ['nodeId' => 1, 'parentId' => -1, 'title' => 'Node 1'],
    ['nodeId' => 2, 'parentId' => 1, 'title' => 'Node 1.1'],
    ['nodeId' => 3, 'parentId' => -1, 'title' => 'Node 3'],
    ['nodeId' => 4, 'parentId' => 1, 'title' => 'Node 1.2'],
];
$tree = new BlueM\Tree(
    $data,
    ['rootId' => -1, 'id' => 'nodeId', 'parent' => 'parentId']
);

Updating the tree with new data

// Rebuild the tree from new data
$tree->rebuildWithData($newData);

Retrieving nodes

// Get the top-level nodes (returns array)
$rootNodes = $tree->getRootNodes();

// Get all nodes (returns array)
$allNodes = $tree->getNodes();

// Get a single node by its unique identifier
$node = $tree->getNodeById(12345);

Getting a node’s parent, siblings, children, ancestors and descendants

// Get a node's parent node (will be null for the root node)
$parentNode = $node->getParent();

// Get a node's siblings as an array
$siblings = $node->getSiblings();

// Ditto, but include the node itself (identical to $node->getParent()->getChildren())
$siblings = $node->getSiblingsAndSelf();

// Get a node's preceding sibling (null, if there is no preceding sibling)
$precedingSibling = $node->getPrecedingSibling();

// Get a node's following sibling (null, if there is no following sibling)
$followingSibling = $node->getFollowingSibling();

// Does the node have children?
$bool = $node->hasChildren();

// Get the number of Children
$integer = $node->countChildren();

// Get a node's child nodes
$children = $node->getChildren();

// Get a node's ancestors (parent, grandparent, ...)
$ancestors = $node->getAncestors();

// Ditto, but include the node itself
$ancestorsPlusSelf = $node->getAncestorsAndSelf();

// Get a node's descendants (children, grandchildren, ...)
$descendants = $node->getDescendants();

// Ditto, but include the node itself
$descendantsPlusSelf = $node->getDescendantsAndSelf();

Accessing a node’s properties

// Get a node's ID
$id = $node->getId();

// Get the node's hierarchical level (1-based)
$level = $node->getLevel();

// Access node properties using get() overloaded getters or __get():
$value = $node->get('myproperty');
$value = $node->myproperty;
$value = $node->getMyProperty();

// Get the node's properties as an associative array
$array = $node->toArray();

// Get a string representation (which will be the node ID)
echo "$node";

Example: Using it with literal data

<?php

require 'vendor/autoload.php';

// Create the Tree instance
$tree = new BlueM\Tree([
    ['id' => 1, 'name' => 'Africa'],
    ['id' => 2, 'name' => 'America'],
    ['id' => 3, 'name' => 'Asia'],
    ['id' => 4, 'name' => 'Australia'],
    ['id' => 5, 'name' => 'Europe'],
    ['id' => 6, 'name' => 'Santa Barbara', 'parent' => 8],
    ['id' => 7, 'name' => 'USA', 'parent' => 2],
    ['id' => 8, 'name' => 'California', 'parent' => 7],
    ['id' => 9, 'name' => 'Germany', 'parent' => 5],
    ['id' => 10, 'name' => 'Hamburg', 'parent' => 9],
]);
...
...

Example: Using it with a self-joined database table

<?php

require 'vendor/autoload.php';

// Database setup (or use Doctrine or whatever ...)
$db = new PDO(...);

// SELECT the records in the sort order you need
$stm = $db->query('SELECT id, parent, title FROM tablename ORDER BY title');
$records = $stm->fetchAll(PDO::FETCH_ASSOC);

// Create the Tree instance
$tree = new BlueM\Tree($records);
...
...

JSON serialization

As Tree implements JsonSerializable, a tree can be serialized to JSON. By default, the resulting JSON represents a flat (non-hierarchical) representation of the tree data, which – once decoded from JSON – can be re-fed into a new Tree instance. In version before 3.0, you had to subclass the Tree and the Node class to customize the JSON output. Now, serialization is extracted to an external helper class which can be changed both by setting a constructor argument or at runtime just before serialization. However, the default serialization result is the same as before, so you won’t notice any change in behavior unless you tweaked JSON serialization.

To control the JSON, you can either pass an option jsonSerializer to the constructor (i.e. pass something like ['jsonSerializer' => $mySerializer] as argument 2), which must be an object implementing \BlueM\Tree\Serializer\TreeJsonSerializerInterface. Or you call method setJsonSerializer() on the tree. The latter approach can also be used to re-set serialization behavior to the default by calling it without an argument.

The library comes with two distinct serializers: \BlueM\Tree\Serializer\FlatTreeJsonSerializer is the default, which is used if no serializer is set and which results in the “old”, flat JSON output. Plus, there is \BlueM\Tree\Serializer\HierarchicalTreeJsonSerializer, which creates a hierarchical, depth-first sorted representation of the tree nodes. If you need something else, feel free to write your own serializer.

Handling inconsistent data

If a problem is detected while building the tree (such as a parent reference to the node itself or in invalid parent ID), an InvalidParentException exception is thrown. Often this makes sens, but it might not always. For those cases, you can pass in a callable as value for key buildWarningCallback in the options argument which can be given as argument 2 to Tree’s constructor, and which will be called whenever a problem is seen. The signature of the callable should be like that of method Tree::buildWarningHandler(), which is the default implementation (and which throws the InvalidParentException). For instance, if you would like to just ignore nodes with invalid parent ID, you could pass in an empty callable.

Please note that a node with invalid parent ID will not be added to the tree. If you need to fix the node (for example, use the root node as parent), you could subclass Tree, overwrite buildWarningHandler() and do that in the overwritten method.

Running Tests

PHPUnit is configured as a dev dependency, so running tests is a matter of:

  • composer install
  • ./vendor/bin/phpunit

If you want to see TestDox output or coverage data, you can comment in the commented lines in the <log> section of phpunit.xml.dist.

Version History

3.2 (2021-12-30)

  • Slight modernizations regarding typehints, but apart from that no changes in API or behavior
  • Supresses warnings on PHP 8.1
  • Minimum PHP version is now 7.3 (previously: 7.0)

3.1 (2019-09-15)

  • Building the tree is now more flexible and more extendable:
    • null can be used as root ID
    • Method Tree::build(), which was private before, is now protected, in order to hook into the building process
    • Until version 3.0, in case of a data inconsistency, an InvalidParentException was thrown. Now, the behavior is swappable through a new constructor option “buildWarningCallback” or through subclassing and overwriting method buildWarningHandler()

3.0 (2019-03-28)

  • JSON serialization is easily customizable by setting a custom serializer. (See section “JSON serialization” in this Readme.) Potential BC break: if in your own code, you subclassed Tree or Tree\Node and added an own implementation of jsonSerialize(), your current code might break. This is the only reason for the major version number bump, as everything else is unchanged. It is highly likely that you don’t have to change anything to be compatible with v3.
  • License change: BSD-2 to BSD-3

2.0 (2018-02-04)

  • BC break: getAncestors() or getAncestorsAndSelf() no longer include the root node as last item of the returned array. Solution: add it yourself, if you need it.
  • BC break: Removed argument to getAncestors(). Solution: If you passed true as argument before, change this to getAncestorsAndSelf().
  • BC break: Removed argument to getDescendants(). Solution: If you passed true as argument before, change this to getDescendantsAndSelf().
  • BC break: Removed argument to getSiblings(). Solution: If you passed true as argument before, change this to getSiblingsAndSelf().
  • BC break: Moved BlueM\Tree\InvalidParentException to BlueM\Tree\Exception\InvalidParentException. Solution: Update namespace imports.
  • New: Added method Tree::rebuildWithData() to rebuild the tree with new data.
  • New: Tree and Tree\Node implement JsonSerializable and provide default implementations, which means that you can easily serialize the whole tree oder nodes to JSON.
  • New: The tree data no longer has to be an array, but instead it must be an iterable, which means that you can either pass in an array or an object implementing the Traversable interface. Also, the data for a node no longer has to be an array, but can also be an object implementing the Iterator interface. These changes should make working with the library more flexible.
  • Internal change: Changed autoloading from PSR-0 to PSR-4, renamed sources’ directory from lib/ to src/ and tests’ directory from test/ to tests/.
  • Internal change: Code modernization, which now requires PHP >= 7.0

1.5.3 (2016-05-20)

  • Handle IDs of mixed type (strings and integers)

1.5.2 (2016-05-10)

  • Add info on JSON serialization in Readme. No code changes.

1.5.1 (2016-01-16)

  • Remove superfluous 2nd argument to build() in constructor

1.5 (2015-01-14)

  • Added createNode() method to Tree, which makes it possible to use instances of a Node subclass as nodes

1.4 (2015-01-07)

  • Added getSiblingsAndSelf() method on Node class.
  • The argument to getSiblings() is deprecated and will be removed in version 2

1.3 (2014-11-07)

  • Added getNodeByValuePath() method on Tree class, which can be used to find a node deeply nested in the tree based on ancestors’ and the node’s values for an arbitrary property. (See method doc comment for example.)

1.2 (2014-10-14)

  • Implemented __isset() and __get() on the Node class. This makes it possible to pass nodes to Twig (or other libraries that handle object properties similarly) and to access nodes’ properties intuitively.
  • Improved case-insensitive handling of node properties

1.1 (2014-09-24)

  • Added getDescendantsAndSelf()
  • Added getAncestorsAndSelf()
  • Arguments to getDescendants() and getAncestors() are deprecated and will be removed with version 2
  • Added a check to make sure that nodes don’t use their own ID as parent ID. This throws an exception which would not have been thrown before if this is the case. Hence, it might break backward compatibility, but only if the data data is inconsistent.

1.0 (2014-06-26)

  • First public release

Author & License

This code was written by Carsten Blüm (www.bluem.net) and licensed under the BSD 3-Clause license.

tree's People

Contributors

bluem avatar simpod avatar zonky2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tree's Issues

tree with max 3 children for each node

Hello,
i have mysql table structured for tree where each node have maximum 3 nodes in each level.
Example node1 is in row=1 & column=1
node 1 has 3 childrens where row=2 & column=1,=2, =3
next row is row=3 and have 9 possibles of column from col=1 to col=9

How i can use your code to insert new node in his right position if i know the parent
Exmaple if i want insert new node for parent node1(row=1, col=1) the logic must be row=3 & col=1

in my db structure each node saved in 1 record with data: id, id_parent, row, column,id_reffer

id_parent is the parent id of direct sub level
id_reffer is the parent id first level

Can help me? Thanks

ErrorException Notice: Undefined index: parent

ErrorException
in \vendor/bluem/tree/src/Tree.php (line 235)

230 $row = iterator_to_array($row);
231 }
232 $this->nodes[$row[$this->idKey]] = $this->createNode(
233
234 $row[$this->idKey],
235 $row[$this->parentKey],
236 $row
237 );
238
239 if (empty($children[$row[$this->parentKey]])) {
240
erreur Bluem tree
$children[$row[$this->parentKey]] = [$row[$this->idKey]];

Hello can you help me?

"getNodeById" returns non-existent nodes

\BlueM\Tree::getNodeById() returns non-existent nodes:

$data = [];
$sut = new BlueM\Tree($data);

// #1: returns a "\BlueM\Tree\Node" (incorrect)
var_dump($sut->getNodeById(0));

// #2: throws InvalidArgumentException (correct)
var_dump($sut->getNodeById(1));

Expected behavior: when an id does not exist, an \InvalidArgumentException should be thrown.


Details

There seems to be a problem with 0 (int), '0' (string) and false (bool):

// arrange
$data = [];
$sut = new BlueM\Tree($data);

$cases = [-1, 0, 1, '-1', '0', '1', PHP_INT_MIN, PHP_INT_MAX, true, false, null];
foreach ($cases as $case) {
    try {
        // act
        $result = $sut->getNodeById($case)->toArray();

        // assert
        assert(!is_array($result), 'fail: FIXME');

    } catch (InvalidArgumentException $e) {
        var_dump(['case' => $case, 'result' => 'pass']);

    } catch (Throwable $e) {
        var_dump(['case' => $case, 'result' => $e->getMessage()]);
    }
}

Result:

array (size=2)
  'case' => int -1
  'result' => string 'pass' (length=4)

array (size=2)
  'case' => int 0
  'result' => string 'fail: FIXME' (length=11)

array (size=2)
  'case' => int 1
  'result' => string 'pass' (length=4)

array (size=2)
  'case' => string '-1' (length=2)
  'result' => string 'pass' (length=4)

array (size=2)
  'case' => string '0' (length=1)
  'result' => string 'fail: FIXME' (length=11)

array (size=2)
  'case' => string '1' (length=1)
  'result' => string 'pass' (length=4)

array (size=2)
  'case' => int -9223372036854775808
  'result' => string 'pass' (length=4)

array (size=2)
  'case' => int 9223372036854775807
  'result' => string 'pass' (length=4)

array (size=2)
  'case' => boolean true
  'result' => string 'pass' (length=4)

array (size=2)
  'case' => boolean false
  'result' => string 'fail: FIXME' (length=11)

array (size=2)
  'case' => null
  'result' => string 'pass' (length=4)

Format question : how to remove keys?

Hi,
Thanks a lot for your wonderfull tool, it works very well. Nevertheless i have a question, after creating the tree and outputting the json hierarchical tree i have:

{
	"14": {
		"name": "2 Vous \u00eates",
		"title": "2 Vous \u00eates",
		"id": 2,
		"parent": 0,
		"children": {
			"0": {
				"name": "291 Etes-vous enceinte ?",
				"title": "291 Etes-vous enceinte ?",
				"id": 291,
				"parent": 2
			}
		}
	},
...

nevertheless, what i would like to obtain is somthing formatted like this:

{
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "AgglomerativeCluster", "value": 3938},
      {"name": "CommunityStructure", "value": 3812},
      {"name": "HierarchicalCluster", "value": 6714},
      {"name": "MergeEdge", "value": 743}
     ]
    },
...

Is this possible ?
Thanks a lot

Support invalidating or rebuilding the tree (?)

A few times, I had the need to rebuild the tree with fresh data. This can be easily done, but currently requires creating a new instance, as there is no public API for refreshing the data. Creating a new instance is simple, but if instantiation can be avoided, this is a win.

Another thought: could it be useful to enable Tree to fetch (or refetch) data instead of pushing the data into the constructor (or in some other method)?

Add an iterator (?)

Just an idea: would an iterator – to traverse the whole tree or part of the tree – be useful, in addition to the iteration methods currently available?

how to change object to array

how to write to array?

 BlueM\Tree\Node Object
    (
        [properties:protected] => Array
            (
                [title] => 点心/蛋糕
                [id] => 1
                [parent] => 0
            )

        [parent:protected] => BlueM\Tree\Node Object
            (
                [properties:protected] => Array
                    (
                        [id] => 0
                        [parent] => 
                    )

                [parent:protected] => 
                [children:protected] => Array
                    (
                        [0] => BlueM\Tree\Node Object

                    )

            )

Make customization of JSON serialization more flexible

Currently, it is required to:

  • Overwrite the node class (implement at least 1 method)
  • Overwrite the tree class (implement at least 2 methods; 1 for JSON, 1 for custom node class)

Would be nicer to get along without subclassing at all. Basic concept could be: externalize the serialization, offer several serialization strategies (and pick a default strategy which produces the same JSON as the current implementation) and make them selectable.

Motivation: see #16.

Check if node has been visited

Hello, I need to check when I already visited a node when traversing through a tree. In the array of arrays that I used to create the tree I added a "visited" key to each node but when I try to update said key

$node->visited = true

the node isn't updating the value of the visited property, I don't know if this is the expected behavior and if so, is there any native way to check if the node has already been visited?

own ID as parent ID exception

My data:

    {
        "id": "moblie_prj",
        "name": "my project",
        "parent": "0"
    },

this data throw exception Node with ID $id references its own ID as parent ID

I found that Tree.php (line 188) compare of two string should be === instead of ==.

"getAncestorsGeneric" fails to return the last ancestor

Since version 2.0, the method Node::getAncestorsGeneric does not return the last ancestor of the set of nodes. In version 1.5.3, the method did not exist and the original method looked like this :

    public function getAncestors($includeSelf = false)
    {
        $ancestors = $includeSelf ? array($this) : array();

        if (null === $this->parent) {
            return $ancestors;
        }

        return array_merge($ancestors, $this->parent->getAncestors(true));
    }

It works fine, since if the current node has no parent, the recursive iteration ends and the current node is returned. Since 2.0, the method getAncestors uses the method getAncestorsGeneric which looks like this :

    protected function getAncestorsGeneric(bool $includeSelf): array
    {
        if (null === $this->parent) {
            return [];
        }

        return array_merge($includeSelf ? [$this] : [], $this->parent->getAncestorsGeneric(true));
    }

This means that if the current node has no parent, an empty array will be returned instead of the current node. This is fine if $includeSelf equals false, but if I have a data set with for example 2 nodes, 1 root and 1 child, the method will ultimately return an empty array despite the fact that $includeSelf equals true at some point.

Create tree from array of ArrayAccess objects

Looks like currenty a tree can only be built from array of arrays:

    protected function createNode($id, $parent, array $properties): Node
    {
        return new Node($id, $parent, $properties);
    }

It would be great if tree could be created from array of ArrayAccess objects.

Personally I use my own tree implementation. But now I want to switch to something modern and community driven.

I looked at nicmart/tree, but looks like it is not maintained.

This projects seems to be maintained and updating to new PHP versions, I would like to use it, but lack of described functionality prevents me from it :(

I always create trees from array of objects (just looked over my last projects - I never build a tree from array of arrays).

Make 'parent' field configurable

I work with data sets that come from other applications that I don't/can't control. The parent field of my data is id_parent and iterating over my data and renaming the filed seems a little bit of an overkill. Can you make the parent field configurable? (As in make it possible to specify what the parent field should be called).

Warning: json_encode(): recursion detected

I have an error when try to use json_encode with $tree->getRootNodes()
This error can be hidden on my develop machine, but the server doesn't return nothign even error

Avoid magic strings for options when building Trees

I think the project will benefit from using constants instead of magic strings when declaring options. This will allow flexibility when renaming options internally in the future, as well as avoiding all issues related to magic strings, both for people contributing to the library and those using it.

I was planning on making a PR, but I figured I should open the discussion first.

I was thinking of making a class that would looking something like this (I only added the options I'm personally using in my project):

<?php

namespace BlueM\Tree;

class Options
{
    const PARENT_KEY = 'parent';
    const ID_KEY = 'id';
    const ROOT_ID = 'rootid';
}

This would allow implementations to change like this:

         $tree = new Tree(
             $data,
             [
-                'id' => 'name',
-                'rootId' => null,
             ]
         );
         $tree = new Tree(
             $data,
             [
+                Tree\Options::ID_KEY => 'name',
+                Tree\Options::ROOT_ID => null,
             ]
         );

And the constructor method for Tree would change slightly (I don't have a diff for this because I was working locally on my vendor folder, as a proof of concept)

        if (!empty($options[Options::ID_KEY])) {
            if (!\is_string($options[Options::ID_KEY])) {
                throw new \InvalidArgumentException('Option “ID_KEY” must be a string');
            }
            $this->idKey = $options[Options::ID_KEY];
        }

This would maintain backward compatibility.

Thoughts?

Getting whole tree as JSON object?

Hi,

Sorry if I'm missing something - but I have an array of arrays, passed into the Tree constructor - ids and parent ids set correctly, not getting any errors.

But when I json_encode the result.. it's just a flat array as it was when I passed it? There's no hierarchy, no nesting of nodes?

Implement JsonSerializable

Nodes (maybe also the whole tree) should include a sensible default implementation of JsonSerializable to make them JSON-serializable.

Bug in Tree Constructor

 public function __construct(array $data, array $options = array())
    {
        $this->options = array_change_key_case($options, CASE_LOWER);
        if (!isset($this->options['rootid'])) {
            $this->options['rootid'] = 0;
        }

        $this->build($data, $options);
    }

Your changing the case of the options index but passing down the original options , should be

 $this->build($data, $this->options);

Handle malformed data

Branched from discussion in: #22

There exists a need to provide the ability to require validation of the provided data against an expected schema. By default, this should throw a new MalformedDataException (or similar) that stores information about which data attribute was missing or was otherwise malformed (i.e. key is a string instead of int), and in what way it was missing or malformed.

Performing malformed-data error checking should be enabled by default, but easily disabled. This is necessary to maintain performance on very large data sets that you know will have the right structure, such as the results of a well-written SQL statement using PDO::FETCH_ASSOC or similar.

Here is good discussion of options to validate an array against a schema: https://stackoverflow.com/questions/4036708/how-can-i-validate-the-structure-of-my-php-arrays

// Somewhere around L216 in Tree.php, immediately inside of "foreach ($data as $rows)"
if ($this->malformedDataHandler !== false)
{
    $malformedData = array_diff(array_merge_recursive($arrCandidate, $arrModel), $arrModel));
    if (sizeof($malformedData))
    {
        call_user_func($this->malformedDataHandler, $row);
    }
}

I suggest putting it inside of the foreach so that the entire dataset doesn't have to be traversed twice. Once to get the $malformedData, if any, and then again to process it. It would be worth testing the tradeoff of checking for malformed data all at once, which would require a full re-iteration of the array, but that may end up actually being quicker than doing the array_merge_recursive() and array_diff() over every node inline.

The above suggestion would allow the user to set $malformedDataHandler = false; and disable checking/handling of the data vs the schema, and just allow PHP to log its E_NOTICE given that malformed data is encountered.

Ignore parentless nodes

I get my list from an external API, and it, unfortunately, contains parentless nodes. So when building a tree, it keeps throwing an exception "Node with ID $id points to non-existent parent with ID $pid".

What's the best approach for ignoring these?

Get return Value or null

Node::Get

why throw an exeption and not null? I've the problem there are parents with an propertie or the propertie is unset. If I initialize it with null and call the get-method from the node I get the exeption

Best regrets

Magnus

Calculate max depth

I noticed that there is a method that brings the level of the category.
Is there any way to return to the maximum depth?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.