Dirk80 has asked for the wisdom of the Perl Monks concerning the following question:
Hello
possibly this is an easy thing. But I don't get it. So I'm interested in your answers.
Here my string:
my $str = "1. ...... AB_CD 1.1 ...... EF_GH 1.2 .... IJ_KL_MN 2. ............ OPQR";
And here what I would like to have:
my $VAR1 = [{'chapter' => 1, 'name' => 'AB_CD'},{'chapter' => 1.1,'nam
+e' => 'EF_GH'},{'chapter' => 1.2,'name' => 'IJ_KL_MN'},{'chapter' =>
+2,'name' => 'OPQR'}];
I tried a lot of things with split. And I often came near to the desired result. But as said before. I didn't get it completely correctly.
Example I tried: split(/\s\.+\s/, $str);
Thanks alot for your help.
Greetings, Dirk
Re: Convert string to data structure
by Kenosis (Priest) on Sep 21, 2012 at 16:02 UTC
|
use Modern::Perl;
use Data::Dumper;
my @array;
my $str =
"1. ...... AB_CD 1.1 ...... EF_GH 1.2 .... IJ_KL_MN 2. ............
+OPQR";
while ( $str =~ /(\d+\.\d*)\s+\.+\s+(\S+)\s*/g ) {
push @array, { chapter => $1, name => $2 };
}
say Dumper \@array;
Output:
$VAR1 = [
{
'name' => 'AB_CD',
'chapter' => '1.'
},
{
'name' => 'EF_GH',
'chapter' => '1.1'
},
{
'name' => 'IJ_KL_MN',
'chapter' => '1.2'
},
{
'name' => 'OPQR',
'chapter' => '2.'
}
];
The regex:
/(\d+\.\d*)\s+\.+\s+(\S+)\s*/g
^ ^ ^ ^ ^ ^ ^ ^ ^
| | | | | | | | |
| | | | | | | | + - Globally
| | | | | | | + - 0+ spaces
| | | | | | + - Capture non-whitespace characters
| | | | | + - 1+ spaces
| | | | + - Multiple periods
| | | + - 1+ spaces
| | + - Capture zero or more digits
| + - Capture a period
+ - Capture one or more digits
Hope this helps! | [reply] [d/l] [select] |
|
Thank you very much. All your answers are so great. And it was interesting to try all. A lot of great techniques. I could learn a lot of new skills and got ideas how to solve such a problem.
Especially this solution "matching operator in global mode" I like because it is very easy to understand.
| [reply] |
Re: Convert string to data structure
by Limbic~Region (Chancellor) on Sep 21, 2012 at 15:40 UTC
|
Dirk80,
Something like this untested code might work:
my @token = split ' ', $str;
for my $idx (reverse 0 .. $#token) {
my $item = $token[$idx];
$item =~ s/\.+$//;
splice(@token, $idx, 1) if ! length($item);
}
my @structure;
for my $idx (grep {$_ % 2} 1 .. $#token) {
push @structure, {
chapter => $token{$idx - 1},
name => $toekn{$idx}
};
}
| [reply] [d/l] |
Re: Convert string to data structure
by Athanasius (Archbishop) on Sep 21, 2012 at 15:52 UTC
|
#! perl
use strict;
use warnings;
use Data::Dumper;
my $str = "1. ...... AB_CD 1.1 ...... EF_GH 1.2 .... IJ_KL_MN 2. .....
+....... OPQR";
$str =~ s/ \.{2,} //gx;
$str =~ s/ \.\s //gx;
my %terms = split(/\s+/, $str);
my @array;
push @array, { 'chapter' => $_, 'name' => $terms{$_} } for sort keys %
+terms;
print Dumper(\@array);
Output:
$VAR1 = [
{
'name' => 'AB_CD',
'chapter' => '1'
},
{
'name' => 'EF_GH',
'chapter' => '1.1'
},
{
'name' => 'IJ_KL_MN',
'chapter' => '1.2'
},
{
'name' => 'OPQR',
'chapter' => '2'
}
];
Hope that helps,
Athanasius <°(((>< contra mundum
| [reply] [d/l] [select] |
Re: Convert string to data structure (split)
by tye (Sage) on Sep 21, 2012 at 15:56 UTC
|
my $str = "1. ...... AB_CD 1.1 ...... EF_GH 1.2 .... IJ_KL_MN 2. .....
+....... OPQR";
my( undef, %chap ) = split /\s*(\d+\.\d*)\s*\.+\s*/, $str;
Works.
| [reply] [d/l] |
|
split/\s+(\d+ ...
# ^
to
split/\s*(\d+ ...
# ^
otherwise it fails to capture '1.' => 'AB_CD'.
Athanasius <°(((>< contra mundum
| [reply] [d/l] [select] |
|
| [reply] |
Re: Convert string to data structure
by johngg (Canon) on Sep 21, 2012 at 16:52 UTC
|
$ perl -MData::Dumper -Mstrict -Mwarnings -E '
> my $str =
> q{1. ...... AB_CD 1.1 ...... EF_GH 1.2 .... IJ_KL_MN 2. .........
+... OPQR};
> my $raChapters = [
> map { { chapter => $_->[ 0 ], name => $_->[ 1 ] } }
> map { [ split m{[. ]{2,}} ] }
> split m{ (?=\d)}, $str
> ];
> print Data::Dumper->Dumpxs( [ $raChapters ], [ qw{ raChapters } ] );
+'
$raChapters = [
{
'name' => 'AB_CD',
'chapter' => '1'
},
{
'name' => 'EF_GH',
'chapter' => '1.1'
},
{
'name' => 'IJ_KL_MN',
'chapter' => '1.2'
},
{
'name' => 'OPQR',
'chapter' => '2'
}
];
$
| [reply] [d/l] |
Re: Convert string to data structure
by BrowserUk (Patriarch) on Sep 21, 2012 at 18:28 UTC
|
$s = "1. ...... AB_CD 1.1 ...... EF_GH 1.2 .... IJ_KL_MN 2. ..........
+.. OPQR";;
@a = map{
/(\S+)\s+\.+\s+(\S+)/;
{ chapter => $1, name => $2 }
} split '(?<=[^.])\s(?=[^.])', $s;;
pp \@a;;
[
{ chapter => "1.", name => "AB_CD" },
{ chapter => "1.1", name => "EF_GH" },
{ chapter => "1.2", name => "IJ_KL_MN" },
{ chapter => "2.", name => "OPQR" },
]
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
RIP Neil Armstrong
| [reply] [d/l] |
Re: Convert string to data structure
by jdporter (Paladin) on Sep 21, 2012 at 18:44 UTC
|
my @a = map {
my %h;
@h{qw( chapter name )} = split / \.+ /;
\%h
} split / (?=\d)/, $str;
| [reply] [d/l] |
|
|