Perl add Hash to Hash of Hashes at the end

Go To StackoverFlow.com

0

I am trying to add hash to my hash of hashes like this:

  %funkce = (
    "funkce1" => {
      "file" => "soubor1",
      "name" => "jmeno1",
      "varargs" => "args",
      "rettype" => "navrat",
      "params" => [
                "typ",
                "typ2"
            ]
    },
    "funkce2" => {
      "file" => "soubor2",
      "name" => "jmeno2",
      "varargs" => "args",
      "rettype" => "navrat",
      "params" => [
          "typ",
          "typ2"
      ]
    }
  );
  $delka = keys %funkce;
  $funkce{ "funkce" . ($delka + 1)} = {
      "file" => "soubor3",
      "name" => "jmeno3",
      "varargs" => "args",
      "rettype" => "navrat",
      "params" => [
          "typ",
          "typ2"
        ]
    };

But there is a problem. The last one hash is add as first in %function but I want It as a last one. How can I fix it? And I am doing it right? Thanks

2012-04-05 20:24
by Libor Zapletal


1

Hashes do not guarantee insert order. You're asking it to hash your key, so x > y <=/=> f(x) > f(y)

If you want to guarantee insert order, although I see no reason to introduce the overhead (of a tie), a standard way is to use Tie::IxHash.

Lists have ends, not hashes. Hashes are a mathematical mapping from a set of names or ids to a set of objects or values. If we think of dog names to dogs then, despite that we can arrange the names of the dogs alphabetically, there really is no "first dog".

From what you show,

push( @funkce
    , { "file"    => "soubor1"
      , "name"    => "jmeno1"
      , "varargs" => "args"
      , "rettype" => "navrat"
      , "params"  => [ qw<typ typ2> ]
      });

will work just as good. There is little gain in typing $funkce{'funcke2'} rather than $funkce[2] or $funkce{ '$funkce' . $i } over $funkce[$i] and if you're going to increment other names besides, then you should have your division in this fashion: $funkce{'funkce'}[2] // $funkce{'superfunkce'}[2]

Using hashes for discrete parts of names and arrays for numbers is a good way to program your data. $funkce{'funkce'}[2] is every bit a singular entity as $funkce{'funkce2'}.

2012-04-05 20:29
by Axeman
And is there way how can I "fix" it? Some trick - Libor Zapletal 2012-04-05 20:33
@Bibo, why do you need it - Axeman 2012-04-05 20:40
@Bibo You could always sort the keys if you really need them in a particular order - Neil 2012-04-05 20:40
Since when have you been using that style? : - brian d foy 2012-04-05 21:27
There is nothing to fix. Hashes represent a mathematical set. An element is either a set or isn't. Ordered elements are called sequences and there other data structures for that, like arrays or lists. "Hashing" itself means "scrambling": the key is put through a meat-grinder-like "hashing function" which produces a number, which has nothing to do with any order. That number is used to compute the index into a table where to locate the value for that key - Kaz 2012-04-05 21:31
@briandfoy, Since reading PBP. Actually comma-first is NOT recommended by Damien, who suggests the comma-after-every-pair style, but it seemed to with the operator-first look, which I reluctantly agreed to after Damien demonstrated its readability. The nice, clean line just appealed to me once I started putting operators first - Axeman 2012-04-06 12:14
See Tie::Hash::Indexed for a faster alternative to IxHash - daxim 2012-04-07 00:54


0

If you need ordered items use an array, if you want named (unordered) items use a hash. To get something close to ordered hashes, you need either nested arrays/hashes or sort the hashes or use some tied class.

Nesting

 @funkce = (
    { name => "funkce1",
      "file" => "soubor1",
      "name" => "jmeno1",
      "varargs" => "args",
      "rettype" => "navrat",
      "params" => [
                "typ",
                "typ2"
            ]
    },
    { name => "funkce2",
      "file" => "soubor2",
      "name" => "jmeno2",
      "varargs" => "args",
      "rettype" => "navrat",
      "params" => [
          "typ",
          "typ2"
      ]
    }
  );
 push @funkce, {
  name => "funkce3",
  "file" => "soubor3",
  "name" => "jmeno3",
  "varargs" => "args",
  "rettype" => "navrat",
  "params" => [
      "typ",
      "typ2"
    ]
};

Sorting

%funkce = ( ... ); # as in OP

# when using
foreach my $item (sort keys %funkce) {
  # do something with $funkce{$item}
}

Tied

See Tie::IxHash but as Axeman said, you probably don't need/want this.

2012-04-05 20:52
by Joel Berger
Ads