in reply to Re^2: Dive data with automatic array indexing
in thread Dive data with automatic array indexing

Okay. Have a better appreciation of your constraints. Have played around with your code a bit and I think it covers all of the cases that you showed well. There may be a bit of an opportunity to make the config file syntax a little less visually cluttered though.

If you can trust that there are empty lines between the blocks and not within, you can strip off the need for the > or < symbols at the start of each line. Also if you just assume an empty selector means >, then you only have to place the < selectors in cases where you don't want to nudge the index forward. Check out the example DATA below the code. The code will still parse your original example as well if you don't like these changes.

All bugs are mine after twisting your code around like this:

use strict; use warnings; use Data::Diver qw( DiveVal DiveError ); use Data::Dumper qw( Dumper ); my $state = { }; my $ref = [ ]; my $prefix = '<'; while (<DATA>) { chomp; next if /^\s*#.*$/; if (/^\s*$/) { $prefix = '>'; next; }; my ($selector, $value) = split /\s*=\s*/; next unless defined $selector; my @selector = split /\./, $selector =~ s/\.$/.>/r; unshift(@selector, $prefix) unless $selector =~ /^[><]\./; _dive( $ref, \@selector, $value ); $prefix = '<'; } print Dumper $ref; sub _dive { my ( $ref, $selector, $value ) = @_; return unless defined $ref and defined $selector and scalar @$sele +ctor; my @selector_b; for ( @$selector ) { if ( /^(>|<|)$/ ) { my $selector_b = join '.', @selector_b; if ( $1 eq '<') { push @selector_b, $state->{$selector_b} //= 0; } else { $state->{$selector_b} += defined $state->{$selector_b} + ? 1 : 0; push @selector_b, $state->{$selector_b}; } } else { push @selector_b, $_; } } DiveVal( $ref, @selector_b ) = $value; my ( $error ) = DiveError( ); $error and warn $error; return 1; } __DATA__ name = john location = uk interests. = programming interests. = cycling name = laura location = interests. = knitting interests. = tennis interests. = dancing name location = canada interests.. = dogs interests.<. = horses interests. = cars # test.error = blah

Replies are listed 'Best First'.
Re^4: Dive data with automatic array indexing
by peterp (Sexton) on Oct 27, 2014 at 13:51 UTC

    Hi Loops,

    Thank you once again.

    I haven't yet tested your version, but have spent some time reading / understanding its functionality. It appears to be a much more elegant solution. I particularly approve its ability to try to do the right thing when a selectee is blank / missing, this will be beneficial in shortening long url query strings, I now wonder if its possible to do something similar with repetitive hash keys. I also thought the block handling the += was nicely thought out, I was unable to come up with a one line notation myself, though I will probably combine the push to remain consistent with the corresponding if. Finally, due to using an outdated Perl version, I will have to write an alternative to the regexp r flag (handle in two steps, or use do).

    I will have to perform vigorous testing and get back to you if I have any outstanding concerns, but this was exactly what I needed, you've killed two birds with one two stones between your two replies, I'm very grateful for your expertise and time. I'm also working on an _undive function (reverse dive / ref to selector), which is proving to be tricky, but I'm getting there.

    Chris