12

I have a Javascript hash table, like so:

var things = [ ];
things["hello"] = {"name" : "zzz I fell asleep", "number" : 7};
things["one"] = {"name" : "something", "number" : 18};
things["two"] = {"name" : "another thing", "number" : -2};

I want to sort these into order by name, so if I iterate through the hash table it will go in order

another thing
something
zzz I fell asleep

I tried doing this:

function compareThings(thing1, thing2) {
    var name1 = thing1["name"].toLowerCase();
    var name2 = thing2["name"].toLowerCase();
    if (name1 < name2) {
        return -1;
        }
    if (name1 > name2) {
        return 1;
        }
    return 0;
}

things.sort(compareThings);

But it doesn't seem to work.

Edit: it occurs to me that perhaps a sorted hash table is an oxymoron. If so, what's the best way to get access to a sorted list of the things here?

1
  • You are not having a hastable (aka object) nor a proper array. If you wat to have an object you should initialize it with {} not with []. If you initialize with [] you have an Array, but then do not add to it by means of a["one"] and a["two"] but by a.push(...);. Only after you know what data structure you want, can you bother with sorting. (BTW: foo["bar"] is the same as foo.bar, use the second, it does not clog the code with string literals and lots of square brackets) Commented Nov 17, 2011 at 12:44

5 Answers 5

18

If you want to iterate through a hash table in JavaScript in order, make an array, populate it with the hash keys, and then sort it.

<html>
<body>
<pre>
  <script>
    var things = new Object ();
    things["hello"] = {"name" : "zzz I fell asleep", "number" : 7};
    things["one"] = {"name" : "something", "number" : 18};
    things["two"] = {"name" : "another thing", "number" : -2};
    var keys = [];
    for (var key in things) {
      if (things.hasOwnProperty(key)) {
        keys.push(key);
      }
    }
    keys.sort ();
    for (i in keys) {
      var key = keys[i];
      var value = things[key];
      document.write (key +"="+value+"\n");
    }
  </script>
</pre>
</body>
</html>
Sign up to request clarification or add additional context in comments.

4 Comments

Just a note, the order of iteration of the for...in statement can be arbitrary, there is nothing described in the ECMAScript specification about the order of enumeration of the properties, it is implementation dependent... no guarantees, use with care...
@CMS: So I should use for (var i = 0; i < keys.length; i++) to be strictly correct?
@Kinopiko, exactly, give a look to the following articles for more info: [ 1 ](andrewdupont.net/2006/05/18/…) and [ 2 ](dhtmlkitchen.com/?category=/JavaScript/&date=2007/10/21/…).
You can also build your keys array using Object.keys(things). It's also a good practice to store the array length before the for loop's comparison step, so @CMS's for loop from above could be written like for (var i = 0, l = keys.length; i < l; i++). This avoids repeatedly indexing into the keys.length property for a value that doesn't change.
7

My solution

things.sort(function(a,b){return a.name - b.name;});

1 Comment

OP is using the array things incorrectly so this would not help.
5

I developed a function that sorts a hash table by the key, no matter if the value is a number or a string. It keeps the key if the table is an associated table.

function sortHashTableByKey(hash, key_order, remove_key)
{
    var tmp = [],
        end = [],
        f_order = null;
    remove_key = remove_key || false;
    for (var key in hash)
    {
        if (hash.hasOwnProperty(key))
        {
            tmp.push(hash[key][key_order]);
        }
    }
    if (hash && hash[0] && typeof(hash[0][key_order]) === 'number')
    {
        f_order = function (a, b) { return a - b; };
    }
    tmp.sort(f_order);
    function getHash(hash, value)
    {
        for (k in hash)
        {
            if (hash[k] && hash[k][key_order] === value)
            {
                return { key : k, hash : hash[k] };
            }
        }
    }
    for (var i = 0, l = tmp.length; i < l; i++)
    {
        tmp[i] = getHash(hash, tmp[i]);
        if (remove_key)
        {
            delete tmp[i].hash[key_order];
        }
        if (!hash.length)
        {
            end[tmp[i].key] = tmp[i].hash;
        }
        else
        {
            end.push(tmp[i].hash);
        }
    }
    return end;
}

This will do :

var things = new Object ();
things["hello"] = {"name" : "zzz I fell asleep", "number" : 7};
things["one"] = {"name" : "something", "number" : 18};
things["two"] = {"name" : "another thing", "number" : -2};

things = sortHashTableByKey(things, 'name');

/*
[
  two: { name: 'another thing', number: -2 },
  one: { name: 'something', number: 18 },
  hello: { name: 'zzz I fell asleep', number: 7 }
]
*/

2 Comments

@HaykSaakian, how is being the function coming along? as a human being, I really admire anyone's effort to sustain both state and function beyond the mind/body problem. bravo.
i should have said "doing this" not "being this" @ToddMorrison
2

your parameters are thing1 and thing2, but you're referencing some variables called asp1 and asp2, which, as far as I can tell from the source you've provided, do not exist.

Also, I think what you're looking for is an associative array, which is not instantiated with the [] syntax. See here for more info:

http://www.quirksmode.org/js/associative.html

EDIT: I don't think there's an array in Javascript that'll let you do what you want.

You can have plain old array, which will let you do the custom sorting or you can have an associative array, which will let you have the named values.

With the regular array, you can obviously iterate through the indexes.

With the associative array, you can iterate through the names by doing for (var key in myArray)

2 Comments

Be careful with that for...in syntax. It'll loop over all the properties the object in question has, which includes things other than array keys.
^^ This is true, but shouldn't be an issue as long as it doesn't inherit from anything.
0

same as eeerahul, with keys() and String().localeCompare() :

function sort_by_key(t_kv,v_kv){
  return(Object.keys(t_kv).sort(
    function(a,b){return(
      String(t_kv[a][v_kv]).localeCompare(String(t_kv[b][v_kv])))}))
}

t={two:{s:'two',n:2},three:{s:'three',n:3},one:{s:'one',n:1}}
sort_by_key(t,'n')
    ["one", "two", "three"]
sort_by_key(t,'s')
    ["one", "three", "two"]    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.