Syntax for creating objects with composite keys in JavaScript
Asked Answered
C

3

8

Is there a syntax for passing composite keys, i.e. lists and objects,
like the below example, or is that by-design?

> obj = {[1, 2]: 3};
SyntaxError: Unexpected token [

The second example works fine, it's not bad but I'd like to know if there is an alternative way.

> obj = {};
> obj[[1, 2]] = 3;
3
> [1, 2] in obj;
> true
Corelative answered 16/6, 2011 at 18:18 Comment(2)
Why do you need composite keys?Dugas
@NT3RP, SQL results will be loaded to JavaScript objects and composite keys will be needed.Corelative
F
13

Object property names in JavaScript are at the end just strings, your second example seems to work because the bracket property accessor converts the [1, 2] expression to String (returning "1,2"), for example:

var obj = {};
obj[[1, 2]] = 3;

console.log(obj["1,2"]); // 3

Another example:

var foo = { toString: function () { return "bar"; } },
    obj = {};

obj[foo] = 3; // foo is converted to String ("bar")
console.log(obj["bar"]); // 3

See also:

Fingered answered 16/6, 2011 at 18:23 Comment(8)
so objects are converted into strings, obviously I didn't know thatCorelative
I think you should add something to actually answer the question, he wants to be able to use literal objects. OP could use a = {"1,2": hello} and then access it using a[[1,2]], looks weird but that what OP wants to doUntinged
@Nick Dandoulakis: Yes even arrays are keyed by strings. Try this var arr = ["Hello","World"]; alert(arr["1"]); jsfiddle.net/mendesjuan/27Z4uUntinged
@CMS, @Juan: I could use strings for keys, since JavaScript doesn't support what I want, and the above link to jshashtable seems interesting. I'll have to test it.Corelative
jshashtable looks good, beware that it's based on strict equality, so two objects that look the same do not map to the same object. For the best hashtable implementation, you need to implement a equals and a hashCode method for your objects just like JavaUntinged
@Juan, do you mean, for example, [1, 2] and [2, 1] will have different hashes?Corelative
@Nick: hashes only exist if you implement them, so you could decide if those should yield the same hash code. From their website, it looks like it's not truly a hash map unless you implement it. Without a hash function, everything goes in the same bucket, so it's basically going to search the entire array. What I really meant is that if you do hash.set([1,2], "Hello") and then try to retrieve it using hash.get([1,2]), then that will fail since both arrays are not the same object (using ===). However, a = [1,2];hash.set(a, "Hello"); hash.get(a) will work. Read section 'Hash codes'Untinged
Not sure if this changed over time, but I just attempted to use this, and [1, 2] -> ["1"]Lubalubba
P
3

If you don't want to do string concatenation you can use nested maps, then a wrapper to make the code a less verbose. Here's an example in TypeScript.

class MapMap<Ka, Kb, V> implements Iterable<[Ka, Kb, V]> {
  readonly mm = new Map<Ka, Map<Kb, V>>()

  get(a: Ka, b: Kb): V | undefined {
    const m = this.mm.get(a)
    if (m !== undefined) {
      return m.get(b)
    }
    return undefined
  }

  set(a: Ka, b: Kb, v: V): void {
    let m = this.mm.get(a)
    if (m === undefined) {
      this.mm.set(a, (m = new Map()))
    }
    m.set(b, v)
  }

  *[Symbol.iterator](): Iterator<[Ka, Kb, V]> {
    for (const [a, m] of this.mm) {
      for (const [b, v] of m) {
        yield [a, b, v]
      }
    }
  }
}
Petronius answered 24/1, 2020 at 23:18 Comment(0)
S
1

do you need the [1, 2] to be preserved as an array? what would this exactly enable you to do? I'm not familiar with "composite keys" so maybe a short explanation for link to one to clarify would help me understand your problem better.

if you just want to use [1, 2] as a key, you can always use that as a string:

var obj = {  
  "[1, 2]": 3
}

but again, i would assume you would want to keep [1, 2] as an array.

Sidewheel answered 16/6, 2011 at 18:22 Comment(2)
For objects to be used as keys, every object would have to implement a hashCode method, like Java. Since hashCode is a big source of bugs, JavaScript only keys by stringsUntinged
@JuanMendes re: "Since hashCode is a big source of bugs" - citation needed.Catania

© 2022 - 2024 — McMap. All rights reserved.