I've been banging my head on this awhile and searched many ways. I'm sure this is going to boil down to being really basic.
I have data in an @array that I want to move to a tree in a %hash.
This might be something more appropriate to JSON? But I haven't delved into it before and I don't need to save out/restore this information.
Desire:
Create a dependent tree of USB devices that can nest under each other that can track the end point (deviceC) through a hub (deviceB) and finally the root (deviceA).
Example:
Simplified (I hope ... this isn't from the actual longer script):
I want to convert an array in this format:
my @array = ['deviceA','deviceB','deviceC'];
to multidimensional hashes equal to:
my %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } )
that would dump like:
$VAR1 = {
'deviceA' => {
'deviceB' => {
'deviceC' => ''
}
}
};
For just looking at a single device this isn't necessary, but I'm building out an IOMMU -> PCI Device -> USB map that contains many devices.
NOTES:
- I'm trying to avoid installing CPAN modules so the script is to similar systems (Proxmox VE)
- The last device (deviceC above) has no children
- value '' is fine
- undef would probably work
- mixing the types would work but I need to know how to set that
- I will never need to modify or manipulate the hash once created
- I don't know the right way to recurse the @array to populate the %hash children. * I want the data horizontal for each USB device
- I'd switch to an Object/package but each device can have a different set of children (or none) making it infeasible to know Object names
- Some USB devices have no children (root hubs) ... similar to %hash = ('deviceA' => '')
- Some have 1 child that is the final device ... similar to %hash = ('deviceA' => { 'deviceB' =>'' } )
- Some have multiple steps between the root via additional hub(s) ... similar to %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } ) or more
Starting point :
This is basic and incomplete but will run:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper qw(Dumper);
# data in from parsing usb device path:
my @array = ['deviceA','deviceB','deviceC'];
# needs to be converted to:
my %hash = ('deviceA' => { 'deviceB' => { 'deviceC' => '' } } );
print "\n\%hash:\n" . Dumper \%hash;
Pseudo-code
This section is NOT working code in any form. I'm just trying to make a note of what I'm thinking. I know the format is wrong, I've tried multiple ways to create this and I'd look even dumber showing all of my attempts :)
I'm very new to refs and I'm not going to try and get that right here. The idea below is:
- For each item in @array:
- Create a way (either a ref or a copy of the current hash) that can be used next iteration to place the next child
- Attach item as a child of the previous iteration with an empty value (that can be appended if there is further iteration)
my @array = ['deviceA','deviceB','deviceC'];
my %hash = {};
my %trackref;
for (@array) {
%trackref = %hash; # a copy of the existing that won't change when %hash updates
$hash{last_child} ::append_child:: $_;
}