#! / usr / bin / perl use warnings; use strict; # Data sampling is done as ORDER BY pid DESC, [ORDER] ASC # I’ll not use the database for this now, but I’ll take the selected list my @select = ( # ID PID ORDER OTHER DATA ... {id => 14, pid => 1, ord => 1, data => 'other data'}, {id => 15, pid => 4, ord => 1, data => 'other data'}, {id => 24, pid => 4, ord => 2, data => 'other data'}, {id => 23, pid => 7, ord => 1, data => 'other data'}, {id => 27, pid => 7, ord => 2, data => 'other data'}, {id => 25, pid => 7, ord => 3, data => 'other data'}, {id => 17, pid => 7, ord => 4, data => 'other data'}, {id => 28, pid => 11, ord => 1, data => 'other data'}, {id => 21, pid => 11, ord => 2, data => 'other data'}, {id => 5, pid => 12, ord => 1, data => 'other data'}, {id => 11, pid => 12, ord => 2, data => 'other data'}, {id => 13, pid => 12, ord => 3, data => 'other data'}, {id => 10, pid => 12, ord => 4, data => 'other data'}, {id => 22, pid => 12, ord => 5, data => 'other data'}, {id => 2, pid => 13, ord => 1, data => 'other data'}, {id => 6, pid => 15, ord => 1, data => 'other data'}, {id => 20, pid => 15, ord => 2, data => 'other data'}, {id => 9, pid => 15, ord => 3, data => 'other data'}, {id => 7, pid => 16, ord => 1, data => 'other data'}, {id => 1, pid => 20, ord => 1, data => 'other data'}, {id => 26, pid => 20, ord => 2, data => 'other data'}, {id => 8, pid => 25, ord => 1, data => 'other data'}, # The most important thing is that the root nodes are right at the end {id => 12, pid => 0, ord => 1, data => 'other data'}, {id => 4, pid => 0, ord => 2, data => 'other data'}, {id => 3, pid => 0, ord => 3, data => 'other data'}, {id => 18, pid => 0, ord => 4, data => 'other data'}, {id => 16, pid => 0, ord => 5, data => 'other data'}, {id => 19, pid => 0, ord => 6, data => 'other data'}, ); my% indexes = (); # In this hash we will store the coordinates of the nodes (list key, and order in the list) my% lists = (); # Lists of nodes initially by PID my $ tpid = undef; # Current list PID foreach my $ row (@select) { # It is not known what is the pid of the root nodes, maybe undef, or maybe 0 $ row -> {pid} || = 'root'; # If the current ID of the parent node is not defined, then we substitute it. $ tpid || = $ row -> {pid}; # Set the node level initially 1 $ row -> {level} = 1; # Insert our node in the PID list push @ {$ lists {$ row -> {pid}}}, $ row; # We put down the coordinate for the node $ indexes {$ row -> {id}} = [$ row -> {pid}, $ # {$ lists {$ row -> {pid}}}]; # If there is already a generated list for the current node ID if ($ lists {$ row -> {id}}) { # For this list we put down the new coordinates, that he will join the current list, # order in the new list, and increase the level by 1 map { $ indexes {$ _-> {id}} -> [0] = $ row -> {pid}; $ indexes {$ _-> {id}} -> [1] + = scalar @ {$ lists {$ row -> {pid}}}; $ _-> {level} ++ } @ {$ lists {$ row -> {id}}}; # Join subordinate list to current push @ {$ lists {$ row -> {pid}}}, @ {$ lists {$ row -> {id}}}; # Remove it as unnecessary delete $ lists {$ row -> {id}}; } # If our current PID does not match the node PID, then the list with the current PID is formed to the end if ($ tpid ne $ row -> {pid}) { # Do we have a parent node up to this point, if not, then he will pick up this list # when it comes to turn if ($ indexes {$ tpid}) { # Increase the order of nodes in the parent list from the parent node to the end by the number # nodes of the list being implemented map { $ indexes {$ _} -> [1] + = scalar @ {$ lists {$ tpid}} } @ {$ lists {$ indexes {$ tpid} -> [0]}} [$ indexes {$ tpid} -> [1] + 1 .. $ # {$ lists {$ indexes {$ tpid} -> [ 0]}}]; # put down the new coordinates for the nodes of the list being introduced, # and level relative to parent node map { $ indexes {$ _-> {id}} -> [0] = $ indexes {$ tpid} -> [0]; $ indexes {$ _-> {id}} -> [1] + = $ indexes {$ tpid} -> [1] + 1; $ _-> {level} + = $ lists {$ indexes {$ tpid} -> [0]} -> [$ indexes {$ tpid} -> [1]] -> {level}; } @ {$ lists {$ tpid}}; # Introduce the list relative to the coordinates of the parent node splice @ {$ lists {$ indexes {$ tpid} -> [0]}}, $ indexes {$ tpid} -> [1] + 1, 0, @ {$ $ {$ tpid}}; # Delete the list as useless delete $ lists {$ tpid}; } # We put a new PID $ tpid = $ row -> {pid}; } } # Actually we will have a ready list under the key that we specified for the root nodes. my @result = @ {$ lists {root}}; # We'll see for verification foreach my $ row (@result) { print $ row -> {id}, "\ t", $ row -> {pid}, "\ t", $ row -> {ord}, "\ t", $ row -> {level}, "\ t ", $ row -> {data}," \ n " } one;
Source: https://habr.com/ru/post/67942/
All Articles