4

There are quite a few similar questions but I couldn't get their answers to work.

 let obj = {};

 const key;//a string
 const value;//a string

 obj[key].push(value);

Obviously this doesn't work but I don't know how to do this. I want it to add a new key and value if it doesn't exist, but if it does exist it should append it to the end of the values for that particular key. ie like the normal push action with arrays.

Expected behaviour:

key = 'hello'
value = 'thanks'

obj = {'hello' : ['thanks']}

key = 'goodbye'
value = 'ok'

obj = {'hello' : ['thanks'], 'goodbye' : ['ok']}

key = 'hello'
value = 'why'

obj = {'hello' : ['thanks','why'], 'goodbye' : ['ok']}

The value 'why' is appended to the end for key 'hello'.

EDIT: All values are put into arrays.

5
  • 1
    Why do you do obj = {'hello' : 'thanks'} and not obj = {'hello' : ['thanks']} if you know in advance that hello is going to hold more than one value? Commented Jun 5, 2019 at 6:57
  • @lealceldeiro That's not what I'm doing, that's the expected output, so if it would put it in an array like that then that's fine. Commented Jun 5, 2019 at 6:59
  • Is the value guaranteed to be a string? If the first value is an array, there would be no way to figure out during the second add whether the original value is the array or it has already been converted into an array. Commented Jun 5, 2019 at 7:03
  • @ShioT Yes the values and keys will always be strings. Commented Jun 5, 2019 at 7:04
  • Case in point: obj.add('key', [1, 2]) and obj.add('key', 1); obj.add('key', 2) produces the same object, but they must be treated differently when you try to add one more time. Commented Jun 5, 2019 at 7:04

6 Answers 6

6

You could create custom function for this that checks if the key exists in object and based on that sets value directly or turns it into an array.

let obj = {
  foo: 'bar'
};

let add = (obj, key, val) => {
  if (key in obj) obj[key] = [].concat(obj[key], val);
  else obj[key] = val;
}

add(obj, 'foo', 'baz');
add(obj, 'bar', 'baz');

console.log(obj)

You could also use Proxy with set trap that will run when you try to set new property on proxy object.

const obj = {
  foo: 'bar'
}

const proxy = new Proxy(obj, {
  set(obj, prop, value) {
    if (prop in obj) obj[prop] = [].concat(obj[prop], value)
    else obj[prop] = value;
  }
})

proxy.foo = 'bar';
proxy.bar = 'baz';
console.log(proxy)

Sign up to request clarification or add additional context in comments.

Comments

2

Fairly simple - use the logical OR operator ||:

let obj = {};

const key = "key";
const value = "value";

obj[key] = obj[key] || [];
obj[key].push(value);
obj[key].push("anotherValue");

console.log(obj);
.as-console-wrapper { max-height: 100% !important; top: auto; }

9 Comments

What if you start with {key: "value"} instead of an empty object?
This creates { "key": [ "value" ] } which is not what OP wants. Only if the property is assigned again, it should create an array
@adiga - no - read comment below question
@KamilKiełczewski only if you choose to interpret it that way which seems wrong, as OP expects strings
@KamilKiełczewski that piece of code was a joke...no need to over-analyse its correctness. "To be, or not to be, that is the question"
|
1

You can also do this via Object.assign in a pretty concise way:

let o = {}

let add = (obj, k, v) => Object.assign(obj, obj[k] 
  ? { [k]: [].concat(obj[k], v) } 
  : { [k]: v })

console.log(add(o, 'a', 1))
console.log(add(o, 'b', 2))
console.log(add(o, 'a', 3))
console.log(add(o, 'a', 4))

The idea is to use the ternary operator and check if we already have the key and if so concat it to a new array. otherwise just assign a new object.

Comments

-1

You can create a prototype function for your requirement

Object.prototype.add = function(key, value) {
  if( this[key] != undefined) this[key] = [].concat(this[key], value);
  else this[key] = value;
};

let obj = {'hello' : 'thanks', 'goodbye' : 'ok'}

let key = 'hello'
let value = 'why'
//obj[key] = value;
obj.add(key,value);
console.log(obj)

1 Comment

Why would you need a prototype function for all objects? At best you can create an object with the add functionality and then do Object.create(adder) to derive your new ones.
-1

Try (I take this comment into account)

let obj = {};

const key = 'some_key';//a string
const value = 'first value' ;//a string


obj[key]= (obj[key]||[]).concat(value);
obj[key]= (obj[key]||[]).concat('next value');

console.log(obj);

Comments

-2

Try this. However, this will also put the first value in an array, but that's quite a standard behaviour if you know it's going to be an array of values.

  if(obj[key]){
    obj[key].push(value);
  }
  else{
    obj[key] = [value];
  }

2 Comments

By default, it should just add value, not [value]
@adiga - no - read comment below question

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.