#445 ✓invalid
niuty

$H does not convert associative arrays correctly

Reported by niuty | November 16th, 2008 @ 01:05 AM

Browser: Firefox 2.0.0.18 OS: Mac OS X 10.4.11 Prototype: 1.6.0.3

I am not sure whether this is intended or a bug. When I have an associative array, I would sometimes want to convert it to a Hash for traversal. But when I do that, I would end up with a Hash with a whole bunch of other elements, 39 functions for an Array, to be exact.


var a = new Array();
a.a = 1;
a.b = 2;
var b = $H(a);
b.collect(function(i) { return i });
// -> [["a", 1], ["b", 2], ["each", function()], ["eachSlice", function()], ["all", function()], ["any", function()], ["collect", function()], ["detect", function()], ["findAll", function()], ["grep", function()], ["include", function()], ["inGroupsOf", function()], ["inject", function()], ["invoke", function()], ["max", function()], ["min", function()], ["partition", function()], ["pluck", function()], ["reject", function()], ["sortBy", function()], ["toArray", function()], ["zip", function()], ["size", function()], ["inspect", function()], ["find", function()], ["select", function()], ["member", function()], ["entries", function()], ["_reverse", reverse()], ["_each", forEach()], ["clear", function()], ["first", function()], ["last", function()], ["compact", function()], ["flatten", function()], ["without", function()], ["reduce", function()], ["uniq", function()], ["intersect", function()], ["clone", function()], ["toJSON", function()]]

Comments and changes to this ticket

  • Juriy Zaytsev

    Juriy Zaytsev November 16th, 2008 @ 03:14 AM

    • State changed from “new” to “invalid”

    There are no associative arrays in Javascript.

    What you're seeing is an expected behavior (as Prototype.js extends Array.prototype with additional methods).

    Replace new Array() with {} and it should "work".

    Good luck.

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 01:56 AM

    • Tag changed from 1.6.0.3, array, hash to 1.6.0.3, hash, section:lang

    [not-tagged:"array" tagged:"section:lang" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 02:04 AM

    • Tag changed from 1.6.0.3, hash, section:lang to 1.6.0.3, section:lang

    [not-tagged:"hash" tagged:"section:lang" bulk edit command]

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 02:23 AM

    • Tag changed from 1.6.0.3, section:lang to section:lang

    [not-tagged:"1.6.0.3" bulk edit command]

  • yopai

    yopai April 12th, 2010 @ 11:38 PM

    See also #126

    I agree, having $H() not correctly handling arrays can somehow be problematic. Even if $H()ing an array can be considered a bad practice, it should give the logical result.

    I just had the case :
    I got a PHP structure mixing arrays, associative arrays (non-specific keys, will be looped over), and objects (named keys we'll access directly).

    $db = array( / this is an object : I'll call db.tables, db.relations, .. /
    'tables' => array( / this is an associative array : I'll treat each of the keys /

    'table1' => array( /* object */
      'columns' => array ( /* array */
         0 => array('name' => 'id', 'type' => 'int')
         1 => ...
    

    This array is json_encoded :
    @@@echo 'var db = '.json_encode($db); To be able to loop on associative arrays, I had to convert them into arrays :
    db.tables = $H(db.tables);

    But what if $db['tables'] is empty ? json_encode has no way to know it's an empty associative array, and converts it into an empty JS array.

    As stated in #126, saying "that's a normal behaviour" is not sufficient. At least there should be a big warning in the doc; but handling this case would be preferable.

    My patch :

    I modified Hash#initialize to handle the case where the object is an array (and transformed the ternary operator into an if / elseif / else).
    This is retro-compatible (except if an user would have voluntary use $H on an array and got methods !)
    This shouldn't be performance consumer, as it just runs an additional test on hash creation.

    #126 talks about creating a Array#toObject method... That's maybe a better solution.

    Note (since I also thought to that) : I could have been argued that it's a json_encode() problem; but json_encode()ing with JSON_FORCE_OBJECT param is neither a solution, since the columns is a real array, and I need it to stay an array even it's empty.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

The Prototype JavaScript library.

Shared Ticket Bins

People watching this ticket

Attachments

Referenced by

Pages