Working with a forest of binary trees stored in a large XML file (PHP)

前端 未结 1 1826
予麋鹿
予麋鹿 2021-01-29 01:16

I have an array like \'var1\'=>1.05, \'var2\'=>0.76,... and a forest of binary trees stored in a 100+ MB XML file.




        
相关标签:
1条回答
  • 2021-01-29 01:26

    You're on the right track with XMLReader. Rather conveniently it includes the method expand() which will return a copy of the current node as a DOMNode. This will let you handle each individual Tree in memory with the DOM API.

    As for handling nodes - evaluate and descend recursively.


    Example:

    $data = [
        'var1' => 1.05,
        'var2' => 0.76
    ];
    
    $dom    = new DOMDocument();
    $xpath  = new DOMXPath($dom);
    $reader = new XMLReader();
    $reader->open('forest.xml');
    
    // Read until reaching the first Tree.
    while ($reader->read() && $reader->localName !== 'Tree');
    
    while ($reader->localName === 'Tree') {
        $tree = $dom->importNode($reader->expand(), true);
    
        echo evaluateTree($data, $tree, $xpath), "\n";
    
        // Move on to the next.
        $reader->next('Tree');
    }
    
    $reader->close();
    
    function evaluateTree(array $data, DOMElement $tree, DOMXPath $xpath)
    {
        foreach ($xpath->query('./Node', $tree) as $node) {
            $field    = $xpath->evaluate('string(./SimplePredicate/@field)', $node);
            $operator = $xpath->evaluate('string(./SimplePredicate/@operator)', $node);
            $value    = $xpath->evaluate('string(./SimplePredicate/@value)', $node);
    
            if (evaluatePredicate($data[$field], $operator, $value)) {
                // Descend recursively.
                return evaluateTree($data, $node, $xpath);
            }
        }
    
        // Reached the end of the line.
        return $tree->getAttribute('id');
    }
    
    function evaluatePredicate($left, $operator, $right)
    {
        switch ($operator) {
            case "lessOrEqual":
                return $left <= $right;
            case "greaterThan":
                return $left > $right;
            default:
                return false;
        }
    }
    

    Output:

    4
    
    0 讨论(0)
提交回复
热议问题