tchrist@convex.COM (Tom Christiansen) (12/02/90)
In article <EMV.90Nov30194551@poe.aa.ox.com> emv@ox.com (Ed Vielmetti) writes: >In article <109564@convex.convex.com> tchrist@convex.COM (Tom Christiansen) writes: > > Speaking of frequently asked questions, here are the new ones > for this month (I'll post RSN).... > Any other candidates or suggestions? > >A nice example of how to load data into an associative array with some >kind of <<ENDOFTABLE construct would be welcomed (if it's not already >in there). Or several associative arrays, for that matter. I'd like >to have some way of taking a table > >news/readers rn,nn,trn >news/nntp nntp,nntpxmit,nntplink >gnu binutils,flex,fileutils >x11/games xtrek >lwall rn,patch,perl >ENDOFTABLE > >and turning it into > >$category{"rn"} -> "news/readers,lwall" >$category{"nntpxmit"} -> "news/nntp" >$category{"binutils"} -> "gnu" I don't think this has been asked very often, so I don't think I'll put it in the FAQ unless I see it a lot more often. I don't really envision the FAQ has a list of how to do neat things in Perl; there'll be plenty of that in the Book. It's supposed to be answers to questions about Perl that people ask again and again. What you're asked about is, nonetheless, a nice thing to know how to do, so I'll it answer here. In general, you can load associative arrays this way: %assoc = ( 'key1', 'value1', 'key2', 'value2', 'key3', 'value3', ... 'keyN', 'valueN', ); If you would like this in a <<here document, you can do this: (I've indented the examples for clarity, but you really need the ENDOFTABLE part flush left to the margin, unless you say something like <<"\tENDOFTABLE".) %assoc = split(' ', <<ENDOFTABLE); key1 value1 key2 value2 key3 value3 ... keyN valueN ENDOFTABLE Bear in mind that this will make your program bigger than the previously described method because you end up storing the data as both a string and an array. Now, in your case, you've got things arranged this way: value1 key1a,key1b,key1c value2 key2a,key2b value3 key3a,key3b,key3c,key3c ... This means you're going to have to do some extra processing to turn it around and break it up. for (split(/\n/,<<EOTABLE)) { news/readers rn,nn,trn news/nntp nntp,nntpxmit,nntplink gnu binutils,flex,fileutils x11/games xtrek lwall rn,patch,perl EOTABLE ($value, $keys) = split; for $key (split(/,/, $keys)) { $category{$key} = $value; } } That's a lot of splitting, and probably Randal or Larry will show us a niftier hack using using less obvious but more Perlian magic. I can at least cut down on one split and the cost of storing it all as a string. Put the table at end of the program past a __END__ symbol and load in in by referencing <DATA>. # init while (<DATA>) { ($value, $keys) = split; for $key (split(/,/, $keys)) { $category{$key} = $value; } } # rest of program # blah blah exit 0; __END__ news/readers rn,nn,trn news/nntp nntp,nntpxmit,nntplink gnu binutils,flex,fileutils x11/games xtrek lwall rn,patch,perl Does that answer your question? --tom
emv@ox.com (Ed Vielmetti) (12/03/90)
In article <109679@convex.convex.com> tchrist@convex.COM (Tom Christiansen) writes: I can at least cut down on one split and the cost of storing it all as a string. Put the table at end of the program past a __END__ symbol and load in in by referencing <DATA>. this is what I end up with once I'm done. one of the (unstated) requirements is to have there be only data and not code in the file, so I'm willing to absorb the subroutine call overhead: require 'table.pl'; while (<DATA>) { &table'simple($_, *array) } ; __END__ key1 value1 key2 value2 this works really nice, because I don't have to worry about getting the syntax of the associative array down exactly right in every pass. the table can be updated quite easily just by appending to the file rather than inserting something in the middle too. and since I have a couple of tables that are the same, the code can sit in a package off somewhere else. table.pl looks like this, with various other types of table handling (multiple keys, multiple values, escaping stuff in, etc) defined as I need them. # table.pl. load in various types of tables. package table; sub table'simple { local($_, *ary) = @_; if (!/^[ \t]$/) { ($key,$value) = split; $ary{$key} = $value; } 1; } thanks. --Ed