convertinga directory path into a hash

Z

Zebee Johnstone

I have a unix directory path, say /home/user/mail

Not knowing how long it will be, that is, how many elements, how can I
convert it into a sequence of hashes:
$ref->{'home'}->{'user'}->{'mail'}

zebee
 
Z

Zebee Johnstone

In comp.lang.perl.misc on Tue, 24 Aug 2004 08:43:56 +0200
Christian Winter said:
You could use eval() for that, like:

Thanks! Now to see if the idea that this was a solution
to will work.

between asking and being answered I thought up another solution
but that isn't right, so back to this one.

Zebee
 
T

Tassilo v. Parseval

Also sprach Zebee Johnstone:
I have a unix directory path, say /home/user/mail

Not knowing how long it will be, that is, how many elements, how can I
convert it into a sequence of hashes:
$ref->{'home'}->{'user'}->{'mail'}

This can be done with a simple recursive function:

sub path2hash {
my ($p, $ref) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
path2hash($tail, $ref->{ $head } = {});
return $ref;
}

my $ref = path2hash("/home/user/mail");

Note that using string eval (as recommended elsewhere) looks tempting
for a task like this but it can be done just as well (and even more
safely) without.

Tassilo
 
Z

Zebee Johnstone

In comp.lang.perl.misc on Tue, 24 Aug 2004 09:57:17 +0200
Tassilo v. Parseval said:
Also sprach Zebee Johnstone:
I have a unix directory path, say /home/user/mail

Not knowing how long it will be, that is, how many elements, how can I
convert it into a sequence of hashes:
$ref->{'home'}->{'user'}->{'mail'}

This can be done with a simple recursive function:

sub path2hash {
my ($p, $ref) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
path2hash($tail, $ref->{ $head } = {});

I don't understand what you are passing here, and how the subroutine
sees it.
 
T

Tassilo v. Parseval

Also sprach Zebee Johnstone:
In comp.lang.perl.misc on Tue, 24 Aug 2004 09:57:17 +0200
Tassilo v. Parseval said:
Also sprach Zebee Johnstone:
I have a unix directory path, say /home/user/mail

Not knowing how long it will be, that is, how many elements, how can I
convert it into a sequence of hashes:
$ref->{'home'}->{'user'}->{'mail'}

This can be done with a simple recursive function:

sub path2hash {
my ($p, $ref) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
path2hash($tail, $ref->{ $head } = {});

I don't understand what you are passing here, and how the subroutine
sees it.

It's a short-cut. More explicitely:

$ref->{ $head } = { };
path2hash($tail, $ref->{ $head });

In Perl, assignments have a return value and that was what I was using
here.

Other than that, it should be pretty straight-forward. Note that this is
a so called primitive recursion because each instantiation of the
function cuts off a piece of its argument ($head) and calls path2hash
with the thusly diminshed argument ($tail).

Tassilo
 
U

Uri Guttman

TvP> Also sprach Zebee Johnstone:

TvP> sub path2hash {
TvP> my ($p, $ref) = @_;
TvP> return if not $p;
TvP> my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
TvP> path2hash($tail, $ref->{ $head } = {});
TvP> return $ref;
TvP> }

TvP> my $ref = path2hash("/home/user/mail");

TvP> Note that using string eval (as recommended elsewhere) looks tempting
TvP> for a task like this but it can be done just as well (and even more
TvP> safely) without.

and i wrote a non-recursive version a long while back in my tutorial on
autovivification:

http://sysarch.com/perl/autoviv.txt

look for deep_hash_assign. you would call it by first splitting the path
on / and passing it the list of dir name parts.

uri
 
B

Brian McCauley

I have a unix directory path, say /home/user/mail

Since you don't say where I'll assume it's in $_

I'll also assume you can assume you've got a valid absolute path.
Not knowing how long it will be, that is, how many elements, how can I
convert it into a sequence of hashes:
$ref->{'home'}->{'user'}->{'mail'}

Assming that $ref is initially undef and you want that node to be undef...

{
my $r = \$ref;
$r = \$$r->{$_} for /[^\/]+/g;
}
 
A

Anno Siegel

Tassilo v. Parseval said:
Also sprach Zebee Johnstone:
In comp.lang.perl.misc on Tue, 24 Aug 2004 09:57:17 +0200
Tassilo v. Parseval said:
Also sprach Zebee Johnstone:

I have a unix directory path, say /home/user/mail

Not knowing how long it will be, that is, how many elements, how can I
convert it into a sequence of hashes:
$ref->{'home'}->{'user'}->{'mail'}

This can be done with a simple recursive function:

sub path2hash {
my ($p, $ref) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
path2hash($tail, $ref->{ $head } = {});

I don't understand what you are passing here, and how the subroutine
sees it.

It's a short-cut. More explicitely:

$ref->{ $head } = { };
path2hash($tail, $ref->{ $head });

In Perl, assignments have a return value and that was what I was using
here.

Other than that, it should be pretty straight-forward. Note that this is
a so called primitive recursion because each instantiation of the
function cuts off a piece of its argument ($head) and calls path2hash
with the thusly diminshed argument ($tail).

That means that recursion can be replaced with a jump to the
subroutine. Untested:

sub path2hash {
my ($p, $ref) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
@_ = ( $tail, $ref->{ $head} = {});
goto &path2hash;

"goto &..." is (among other things) Perl's method to cut off tail
recursion.

Anno
 
T

Tassilo v. Parseval

Also sprach Anno Siegel:
It's a short-cut. More explicitely:

$ref->{ $head } = { };
path2hash($tail, $ref->{ $head });

In Perl, assignments have a return value and that was what I was using
here.

Other than that, it should be pretty straight-forward. Note that this is
a so called primitive recursion because each instantiation of the
function cuts off a piece of its argument ($head) and calls path2hash
with the thusly diminshed argument ($tail).

That means that recursion can be replaced with a jump to the
subroutine. Untested:

sub path2hash {
my ($p, $ref) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
@_ = ( $tail, $ref->{ $head} = {});
goto &path2hash;

"goto &..." is (among other things) Perl's method to cut off tail
recursion.

If it had been proper tail recursion, yes. Note that by doing it this
way, you loose the ability to return the populated hash-reference and
you have to do a call-by-reference (sort of). In context, this will
become:

sub path2hash {
my ($p) = @_;
return if not $p;
my ($head, $tail) = $p =~ m!/?([^/]+)(.*)!;
@_ = ($tail, $_[1]->{ $head } = {});
goto &path2hash;
}

path2hash("/home/user/mail", my $ref);

Tassilo
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,159
Messages
2,570,880
Members
47,417
Latest member
DarrenGaun

Latest Threads

Top