[comp.lang.perl] sparse multidim arrays

merlyn@iwarp.intel.com (Randal Schwartz) (03/18/90)

Well, as I was just gettin' cozy last night (alone... :-) in the
waterbed, the following method of doing sparse multidim arrays hit me.
After hacking on it for a half hour today, here's what I came up
with...

================================================== snip
#!/local/merlyn/bin/perl

sub get {
	local(*get'array) = shift;
	local($get'index);
	for $get'index ($[..$#_-1) {
		return undef unless defined $get'array{$_[$get'index]};
		*get'array = $get'array{$_[$get'index]};
	}
	$get'array{$_[$#_]};
}

sub put {
	local($put'value) = shift;
	local(*put'array) = shift;
	local($put'index);
	for $put'index ($[..$#_-1) {
		unless (defined $put'array{$_[$put'index]}) {
			$put'counter++;
			$put'array{$_[$put'index]} = eval "\%put'X$put'counter = (); *put'X$put'counter";
		}
		*put'array = $put'array{$_[$put'index]};
	}
	$put'array{$_[$#_]} = $put'value;
}

sub keys {
	local(*keys'array) = shift;
	local($keys'index);
	for $keys'index ($[..$#_) {
		return undef unless defined $keys'array{$_[$keys'index]};
		*keys'array = $keys'array{$_[$keys'index]};
	}
	keys keys'array;
}

%c = ();

for $i (1..5) {
	for $j (6..9) {
		for $k (10..15) {
			&put("i=$i j=$j k=$k", *c, "I$i", $j*1.001, $k);
		}
	}
}

for $i (sort &keys(*c)) {
	for $j (sort &keys(*c,$i)) {
		for $k (sort &keys(*c,$i,$j)) {
			$value = &get(*c, $i, $j, $k);
			print "$i $j $k: ", defined $value ? $value : "??", "\n";
		}
	}
}
================================================== snip


Basically, the three routines are

	&get(*foo, i1, i2, i3, ...)

fetch the assoc-array element $foo{$i1, $i2, $i3, ...} (conceptually).

	&put($value, *foo, i1, i2, i3 ...)

set the assoc-array element $foo{$i1,$i2,$i3,...} to $value.

	&keys(*foo, i1, i2,....)

return an array of the keys at $foo{$i1,$i2,...}
(of which $i3 would then be a member...)

If someone could take this and clean it up and repost it, I'd be
grateful.  Hopefully, you can reverse-engineer the code.

The method is to have each layer except the last be an assoc-arry of
symbol-table entries.  If an assoc-array isn't present, but I'm trying
to put a value inside it, I create a new one with the funny eval.  It
worked for the few test cases I threw at it.  It *needs* "%foo"
defined, as you can see in my test program.  I tried putting it in
"put" and didn't get any easy success.

What it still needs is: documentation, "undef", and bulletproofing.
Like I said... I have no immediate need for it, so I'm probably not
going to work on it any further, so have at it!

@X=split(//,'Just another Perl hacker,');*Y=*X;print @Y;
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/