sandorado has asked for the wisdom of the Perl Monks concerning the following question:

Hey Monks, it's me again. I have an inputfile. It Looks like this:
<class="abc"> <polygon> <polygon> <rectangle> </class> <class="def"> <polygon> <rectangle> <rectangle> </class>
And my question is, how to save which polygon and rectangle belongs to which class. Because I want to create an Outputfile, where i have to list all Polygons and rectangle. The Polygons and rectangles differs because of coordinates, they also contain. The Output should be like this:
<polygon class ="abc" coordinates=".."> <polygon class="abc" coordinates="--"> #and so on
Could someone explain me, how I should solve this Problem, that every polygon and rectangle know to which class they belong? I thought some hashes could help, but do not know how to create them. Thanks Regards

Replies are listed 'Best First'.
Re: Creation of Hash necessary?
by GrandFather (Saint) on Aug 14, 2014 at 09:33 UTC

    poj gave you some real code for some faked up data, but quite likely it doesn't work for the data you have and it doesn't actually solve the problem you have either. You have actually been given most of the pieces you need and I bet you don't see how they fit together.

    A hash is the right thing to solve part of the problem - it lets you group types of things together. An array is right for a different part of the problem - it lets you have a list of things of the same type. So the data structure you need is a two level hash of arrays.

    The top level of the hash is keyed by shape (polygon, rectangle, ...). The values for the top level hash are references to second level hashes keyed by class (abc, def, ...). The values for the second level hashes are references to arrays. Ignoring how you parse the data to generate the data structure, you end up with something that looks like:

    my %hash = ( polygon => { abc => ["0, 0, 10, 0, 12, 2", "10, 10, 20, 10, 22, 12",], def => ["3, 5, 3, 8, 7, 10"], }, rectangle => { abc => ["-10, -10, 20, 20"], def => ["22, 33, 44, 44", "1, 1, -3, -6"], } );

    which can be printed out using:

    for my $shape (sort keys %hash) { for my $class (sort keys %{$hash{$shape}}) { print <<LINE for @{$hash{$shape}{$class}}; <$shape class ="$class" coordinates="$_"> LINE } }

    Since you've not given anything representing your real data you will have to figure out how to generate the hash from your data for yourself. However the print line above gives the syntax for accessing the array you need to add entries to for a given class and shape.

    Perl is the programming world's equivalent of English
Re: Creation of Hash necessary?
by poj (Abbot) on Aug 14, 2014 at 08:51 UTC
    If your data was well formed XML you could use XML::Twig
    #!perl use strict; use XML::Twig; my $xml = do { local $/; <DATA> }; my $twig = new XML::Twig( twig_handlers =>{ class => \&class}, ); $twig->parse($xml); sub class { my ($t,$elt) = @_; for my $shape ($elt->children){ $shape->set_att('class',$elt->att('id')); $shape->print; print "\n"; } } __DATA__ <data> <class id="abc"> <polygon coordinates=".."/> <polygon coordinates=".."/> <rectangle coordinates=".."/> </class> <class id="def"> <polygon coordinates=".."/> <rectangle coordinates=".."/> <rectangle coordinates=".."/> </class> </data>
    poj
Re: Creation of Hash necessary?
by Anonymous Monk on Aug 14, 2014 at 08:12 UTC
      Hey, thanks for your quick Respons. I know how to create hashes. Sorry for this missunderstanding. it's more about, that I do not know how the hash should look alike in this specific case.

        Hey, thanks for your quick Respons. I know how to create hashes. Sorry for this missunderstanding. it's more about, that I do not know how the hash should look alike in this specific case

        Well if you want to gather up all the classes, maybe hash of arrays

        my %class; $class{def}[0] = $rectangle; $class{def}[1] = $polygon; $class{def}[2] = $rectangle2; $class{jam}[0] = $tangle; $class{jam}[1] = $gon; $class{jam}[2] = $tangle2;

        Now $rectangle/polygon.... could be a string or hash or another array ... whatever makes the most sense :)

         

        rm -rf goners
Re: Creation of Hash necessary?
by Athanasius (Archbishop) on Aug 14, 2014 at 14:01 UTC

    Hello sandorado, and welcome to the Monastery!

    You’ve already been given excellent advice, and GrandFather’s hash design is probably just what you need. But something about your problem description — “how to save which polygon and rectangle belongs to which class” — is making me think that you might benefit from an object-oriented solution. So, in Perl’s spirit of TMTOWTDI, here is an OO approach:

    I have assumed XML as the input and borrowed heavily from poj’s solution using XML::Twig. This OO approach may be overkill for your needs; but, if you’ll need to manipulate your shapes in any non-trivial way, it may provide you with necessary flexibility by de-coupling the shapes from their XML encoding.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Thank you a lot, for these description. It helps me a lot, even it does not solve my Problem completly. But I will try and hope the Twig-Module could help me in the future. regards, sandorado
Re: Creation of Hash necessary?
by choroba (Cardinal) on Aug 14, 2014 at 22:56 UTC
    Using the same sample data as Athanasius and XML::XSH2, a wrapper around XML::LibXML:
    open file.xml ; for /data/class[@id]/* set @class ../@id ; ls /data/class/* | cat > file2 ;
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ