ordered hashes

Discussion in 'Perl Misc' started by Julian, Dec 9, 2008.

  1. Julian

    Julian Guest

    Hi,
    Is there a best practice to implement an "ordered hash" in Perl?

    For example I need to manipulate a csv file: each line is a record with
    a fixed number of fields.

    Here are some solutions but I don't find them very elegant:

    Solution 1:
    Two arrays: the first array holds the keys, the second array holds the
    values.

    my @arrkeys = ("first name", "age", "food"....)
    my @arrvalues = ("joe", 39, "corn flakes",...)


    Solution 2:
    An array of hashes:
    my @orderedhash = (
    { FieldName => "first name", Value => "Joe" },
    { FieldName => "age", Value => 39 },
    ...
    );

    Solution 3:
    An array to keep the order of the field, and then a hash.
    my @fieldnames = ( "first name", "age", "food",...);
    my %h = { "first name" => "joe", "age" => 39,...)

    TIA
    Julian, Dec 9, 2008
    #1
    1. Advertising

  2. Julian

    david Guest

    On Dec 9, 12:22 pm, Julian <julian@invalid> wrote:
    > Hi,
    > Is there a best practice to implement an "ordered hash" in Perl?
    >
    > For example I need to manipulate a csv file: each line is a record with
    > a fixed number of fields.
    >
    > Here are some solutions but I don't find them very elegant:
    >
    > Solution 1:
    > Two arrays: the first array holds the keys, the second array holds the
    > values.
    >
    > my @arrkeys = ("first name", "age", "food"....)
    > my @arrvalues = ("joe", 39, "corn flakes",...)
    >
    > Solution 2:
    > An array of hashes:
    > my @orderedhash = (
    >         { FieldName => "first name", Value => "Joe" },
    >         { FieldName => "age", Value => 39 },
    >         ...
    > );
    >
    > Solution 3:
    > An array to keep the order of the field, and then a hash.
    > my @fieldnames = ( "first name", "age", "food",...);
    > my %h = { "first name" => "joe", "age" => 39,...)
    >
    > TIA


    why do you need an ordered hash ?
    What are you trying to achieve in the program
    david, Dec 9, 2008
    #2
    1. Advertising

  3. On Tue, 09 Dec 2008 11:22:30 +0100,
    Julian <julian@invalid> wrote:
    > Hi,
    > Is there a best practice to implement an "ordered hash" in Perl?


    Tie::IxHash is available from CPAN.

    [snip CSV example]

    I've done things like this in the past, but have always opted to use an
    array with the order of the keys, rather than using an ordered hash.

    YMMV

    Martien
    --
    | Louis Pasteur's theory of germs is
    Martien Verbruggen | ridiculous fiction -- Pierre Pachet,
    | Professor of Physiology at Toulouse,
    | 1872
    Martien Verbruggen, Dec 9, 2008
    #3
  4. Julian

    Julian Guest

    bugbear a écrit :
    > Julian wrote:
    >> Hi,
    >> Is there a best practice to implement an "ordered hash" in Perl?
    >>
    >> For example I need to manipulate a csv file: each line is a record
    >> with a fixed number of fields.

    >
    >
    > That's a 2D array.
    >


    yes, the file is a 2D array. But I'm processing one line at a time (the
    files I'm processing can have hundreds of thousands records).
    A line is a 1D array.
    But for example the 24th field is the social security number, the 25th
    field is the wage, and so on.
    In my program I don't want to write $arr[23] = ..., $arr[24]=...
    A hash of some kind is more appropriate:
    $current_record{SSNumber} = ... , $current_record{Wage} = ...
    Julian, Dec 9, 2008
    #4
  5. Julian

    Julian Guest

    david a écrit :
    > On Dec 9, 12:22 pm, Julian <julian@invalid> wrote:
    >> Hi,
    >> Is there a best practice to implement an "ordered hash" in Perl?
    >>
    >> For example I need to manipulate a csv file: each line is a record with
    >> a fixed number of fields.
    >>
    >> Here are some solutions but I don't find them very elegant:
    >>
    >> Solution 1:
    >> Two arrays: the first array holds the keys, the second array holds the
    >> values.
    >>
    >> my @arrkeys = ("first name", "age", "food"....)
    >> my @arrvalues = ("joe", 39, "corn flakes",...)
    >>
    >> Solution 2:
    >> An array of hashes:
    >> my @orderedhash = (
    >> { FieldName => "first name", Value => "Joe" },
    >> { FieldName => "age", Value => 39 },
    >> ...
    >> );
    >>
    >> Solution 3:
    >> An array to keep the order of the field, and then a hash.
    >> my @fieldnames = ( "first name", "age", "food",...);
    >> my %h = { "first name" => "joe", "age" => 39,...)
    >>
    >> TIA

    >
    > why do you need an ordered hash ?
    > What are you trying to achieve in the program


    It's a generic question. I often manipulate csv files or tab-separated
    files, where each field has some semantic. When I read or write a line,
    I need an array. But when I work on the values of the fields I prefer to
    work on a variable whose name has a meaning rather than on n'th element
    of the array.
    Julian, Dec 9, 2008
    #5
  6. Julian <julian@invalid> wrote:
    >bugbear a écrit :
    >> Julian wrote:
    >>> Is there a best practice to implement an "ordered hash" in Perl?
    >>>
    >>> For example I need to manipulate a csv file: each line is a record
    >>> with a fixed number of fields.

    >>
    >> That's a 2D array.
    >>

    >
    >yes, the file is a 2D array. But I'm processing one line at a time (the
    >files I'm processing can have hundreds of thousands records).
    >A line is a 1D array.


    Then I misunderstand your intial question, too.

    >But for example the 24th field is the social security number, the 25th
    >field is the wage, and so on.


    Why would you want to order SSN and wage? WIth extremely few exceptions
    the SSN will always be larger than the wage.

    >In my program I don't want to write $arr[23] = ..., $arr[24]=...
    >A hash of some kind is more appropriate:
    >$current_record{SSNumber} = ... , $current_record{Wage} = ...


    Ok, then, why don't you do it? Where is the problem?

    jue
    Jürgen Exner, Dec 9, 2008
    #6
  7. Julian

    david Guest

    On Dec 9, 3:41 pm, Julian <julian@invalid> wrote:
    > bugbear a écrit :
    >
    > > Julian wrote:
    > >> Hi,
    > >> Is there a best practice to implement an "ordered hash" in Perl?

    >
    > >> For example I need to manipulate a csv file: each line is a record
    > >> with a fixed number of fields.

    >
    > > That's a 2D array.

    >
    > yes, the file is a 2D array. But I'm processing one line at a time (the
    > files I'm processing can have hundreds of thousands records).
    > A line is a 1D array.
    > But for example the 24th field is the social security number, the 25th
    > field is the wage, and so on.
    > In my program I don't want to write $arr[23] = ..., $arr[24]=...
    > A hash of some kind is more appropriate:
    > $current_record{SSNumber} = ... , $current_record{Wage} = ...


    you try to make something like an enum

    try maybe this

    use constant {
    ...
    ...
    SSNumber=>23,
    Wage=>24
    };
    and then
    $current_record[SSNumber] = ... , $current_record[Wage] = ...
    david, Dec 9, 2008
    #7
  8. Julian

    Ron Bergin Guest

    On Dec 9, 5:41 am, Julian <julian@invalid> wrote:
    > bugbear a écrit :
    >
    > > Julian wrote:
    > >> Hi,
    > >> Is there a best practice to implement an "ordered hash" in Perl?

    >
    > >> For example I need to manipulate a csv file: each line is a record
    > >> with a fixed number of fields.

    >
    > > That's a 2D array.

    >
    > yes, the file is a 2D array. But I'm processing one line at a time (the
    > files I'm processing can have hundreds of thousands records).


    Sounds to me that a database would be far more appropriate and more
    efficient than a flat csv file.
    Ron Bergin, Dec 9, 2008
    #8
  9. >>>>> "J" == Julian <julian@invalid> writes:

    J> It's a generic question. I often manipulate csv files or
    J> tab-separated files, where each field has some semantic. When I
    J> read or write a line, I need an array. But when I work on the
    J> values of the fields I prefer to work on a variable whose name
    J> has a meaning rather than on n'th element of the array.

    my @field_labels = qw/date time transaction_id memo amount quantity total/;

    # ...

    my %item;
    @item{@field_labels} = @fields_from_csv;

    # ...
    # do your processing on the values of %item
    # ...

    my @fields_to_output = @item{@field_labels};

    The trick is to realize that you probably don't need an ordered hash for
    most of the processing you want to do -- you just need to read the line
    from the CSV in a specified order, to match the keys correctly, and you
    need to output the line from the CSV in a specified order, to match what
    the file format expects.

    Charlton



    --
    Charlton Wilbur
    Charlton Wilbur, Dec 9, 2008
    #9
  10. Julian

    Guest

    Julian <julian@invalid> wrote:
    > Hi,
    > Is there a best practice to implement an "ordered hash" in Perl?
    >
    > For example I need to manipulate a csv file: each line is a record with
    > a fixed number of fields.


    Have you looked into a module, like Data::Table, the encapsulates the
    entire table functionality?

    >
    > Here are some solutions but I don't find them very elegant:
    >
    > Solution 1:
    > Two arrays: the first array holds the keys, the second array holds the
    > values.
    >
    > my @arrkeys = ("first name", "age", "food"....)
    > my @arrvalues = ("joe", 39, "corn flakes",...)


    There is no efficient way to look up by field name.

    >
    > Solution 2:
    > An array of hashes:
    > my @orderedhash = (
    > { FieldName => "first name", Value => "Joe" },
    > { FieldName => "age", Value => 39 },
    > ...
    > );


    Again, there is no efficient way to look up by field name.

    >
    > Solution 3:
    > An array to keep the order of the field, and then a hash.
    > my @fieldnames = ( "first name", "age", "food",...);
    > my %h = { "first name" => "joe", "age" => 39,...)


    This is how I would do it, if for some reason I wouldn't use
    a CPAN modules in the first place. @fieldnames would probably only need
    to be used during input and output, not the main processing body.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    The costs of publication of this article were defrayed in part by the
    payment of page charges. This article must therefore be hereby marked
    advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
    this fact.
    , Dec 9, 2008
    #10
  11. Julian

    Jim Gibson Guest

    In article <493e46e6$0$2850$>, Julian
    <julian@invalid> wrote:

    > Hi,
    > Is there a best practice to implement an "ordered hash" in Perl?
    >
    > For example I need to manipulate a csv file: each line is a record with
    > a fixed number of fields.
    >
    > Here are some solutions but I don't find them very elegant:
    >
    > Solution 1:
    > Two arrays: the first array holds the keys, the second array holds the
    > values.
    >
    > my @arrkeys = ("first name", "age", "food"....)
    > my @arrvalues = ("joe", 39, "corn flakes",...)
    >
    >
    > Solution 2:
    > An array of hashes:
    > my @orderedhash = (
    > { FieldName => "first name", Value => "Joe" },
    > { FieldName => "age", Value => 39 },
    > ...
    > );
    >
    > Solution 3:
    > An array to keep the order of the field, and then a hash.
    > my @fieldnames = ( "first name", "age", "food",...);
    > my %h = { "first name" => "joe", "age" => 39,...)


    See 'perldoc -q keep' "How can I always keep my hash sorted?"

    Answer:

    Use a database (e.g., DB_File) or the Tie::IxHash module.

    --
    Jim Gibson
    Jim Gibson, Dec 9, 2008
    #11
  12. Julian

    Uri Guttman Guest

    >>>>> "MV" == Martien Verbruggen <> writes:

    MV> I've done things like this in the past, but have always opted to use an
    MV> array with the order of the keys, rather than using an ordered hash.

    i wrote this about a week ago.

    my @col_names = split( /\t/, <> ) ;

    my %name2col ;
    @name2col{ @col_names } = 0 .. $#col_names ;

    my @wanted_names = qw(
    NAME SADDR1 SADDR2 SADDR3 SADDR4 SADDR5 PHONE1 CUSTFLD3 CUSTFLD4 NOTEPAD ) ;

    while( <> ) {

    my %fields ;

    @fields{@wanted_names} =
    (split( /\t/, $_ ))[ @name2col{ @wanted_names } ] ;


    the last statement is a favorite of mine. triple slicing. but only later
    did i notice that one of the slices was constant and could be factored
    out of the loop.

    show me a better version line in any other lang. :)

    uri

    --
    Uri Guttman ------ -------- http://www.sysarch.com --
    ----- Perl Code Review , Architecture, Development, Training, Support ------
    --------- Free Perl Training --- http://perlhunter.com/college.html ---------
    --------- Gourmet Hot Cocoa Mix ---- http://bestfriendscocoa.com ---------
    Uri Guttman, Dec 9, 2008
    #12
  13. Julian

    Julian Guest

    Thanks folks.
    I'll use Charlton's solution.
    Julian, Dec 11, 2008
    #13
  14. Julian

    Guest

    On Tue, 09 Dec 2008 10:39:07 -0500, Charlton Wilbur <> wrote:

    >>>>>> "J" == Julian <julian@invalid> writes:

    >
    > J> It's a generic question. I often manipulate csv files or
    > J> tab-separated files, where each field has some semantic. When I
    > J> read or write a line, I need an array. But when I work on the
    > J> values of the fields I prefer to work on a variable whose name
    > J> has a meaning rather than on n'th element of the array.
    >
    >my @field_labels = qw/date time transaction_id memo amount quantity total/;
    >
    ># ...
    >
    >my %item;
    >@item{@field_labels} = @fields_from_csv;
    >

    If a hash reference were used instead, would this be how it is written?

    my $refitem = { #add stuff};
    @{$refitem}{@field_labels} = @fields_from_csv;

    sln
    , Dec 11, 2008
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ben Holness

    Hashes of Hashes via subs

    Ben Holness, Oct 5, 2003, in forum: Perl
    Replies:
    8
    Views:
    559
    Ben Holness
    Oct 8, 2003
  2. Steven Arnold

    using hashes as keys in hashes

    Steven Arnold, Nov 23, 2005, in forum: Ruby
    Replies:
    3
    Views:
    159
    Mauricio Fernández
    Nov 23, 2005
  3. Tim O'Donovan

    Hash of hashes, of hashes, of arrays of hashes

    Tim O'Donovan, Oct 27, 2005, in forum: Perl Misc
    Replies:
    5
    Views:
    208
  4. January Weiner

    Ordered hashes

    January Weiner, Mar 1, 2006, in forum: Perl Misc
    Replies:
    6
    Views:
    90
    Anno Siegel
    Mar 2, 2006
  5. DL

    Ordered list inside ordered list

    DL, Nov 9, 2009, in forum: Javascript
    Replies:
    6
    Views:
    322
    Dr J R Stockton
    Nov 21, 2009
Loading...

Share This Page