4

I have a function that takes a JSON object and either creates a new array with an initial element, or adds an element to that array if it already exists:

function pushOrCreate(jsonObj,arrayName,newElement){
    if(jsonObj.hasOwnProperty(arrayName)){
        jsonObj[arrayName].push(newElement);
    }
    else{
        jsonObj[arrayName]=[newElement];
    }
}

Here's a test of this function:

var taskAttributesText='{'+
'"abc":"123",'+
'"xyz":"hello"'+
'}';
var taskAttributes=JSON.parse(taskAttributesText);
pushOrCreate(taskAttributes,"workers","xx8238429");
pushOrCreate(taskAttributes,"workers","aa238232");
console.log(JSON.stringify(taskAttributes));

The function is working correctly, but I'm thinking there must be a simpler way to accomplish this push-or-create operation--it seems like the kind of thing that there's a one-line solution for in Javascript. Is there an easier way to do this?

4
  • Not really, there isn't really any better general simplification (though you can turn hasOwnProperty to just if (jsonObj[arrayName]) Commented Mar 28, 2019 at 3:33
  • 2
    There's no such thing as a JSON array. Nor JSON objects for that matter. JSON is always a string. You're dealing with plain arrays and objects. Commented Mar 28, 2019 at 3:34
  • 1
    there is no such thing as a JSON array - JSON is a String, so has no push method Commented Mar 28, 2019 at 3:35
  • 1
    And don't write taskAttributes like that. var taskAttributes = {abc: 123, xyz: "hello"}. done. Commented Mar 28, 2019 at 3:36

4 Answers 4

2

Forget IFs. How about destructuring assignment and default values -

const pushOrCreate = (key, { [key]:arr = [], ...o }, v) =>
  ({ ...o, [key]: [...arr, v] })

console.log(pushOrCreate('foo', {}, 1))
// { foo: [ 1 ] }

console.log(pushOrCreate('foo', {foo: [1]}, 2))
// { foo: [ 1, 2 ] }

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

3 Comments

A perfect solution +1
I'm confused. Is this intended to create a new object? My goal is to pass in an existing object and add an array property to it or modify the array that's one of its properties.
@sigil This should create a pushOrCreate function with virtually identical functionality as the one you've made. It probably could have used an explanation though as even to me at first glance this looks like gibberish.
1

Just use a one-line conditional:

function pushOrCreate(jsonObj,arrayName,newElement){
    jsonObj[arrayName] ? jsonObj[arrayName].push(newElement) : jsonObj[arrayName] = [newElement];
}

4 Comments

Using a ternary operator to execute a push feels dirty to me.
@AdrianBrand Using a ternary operator is the most succinct way of accomplishing the task... Maybe it's the whole function that feels dirty to you?
The conditional ternary is for assigning one value or the other, it is not for executing side effects like pushing into an array. I would rather OP original code over this.
@AdrianBrand That's simply not true... The rules of JavaScript's very syntax have to allow for the output's usage of everything and anything to be optional. Therefore any JavaScript implementation that doesn't allow this type of usage is a flawed one. I'd take code like this over user633183's answer solely for the readability purposes. There is nothing really objectively wrong with using a ternary operator in such a manner.
1

You can use Ternary Operator

function pushOrCreate(jsonObj,arrayName,newElement){
    jsonObj.hasOwnProperty(arrayName) ? jsonObj[arrayName].push(newElement) : jsonObj[arrayName]=[newElement]
}


var taskAttributesText='{'+
    '"abc":"123",'+
    '"xyz":"hello"'+
'}';
var taskAttributes=JSON.parse(taskAttributesText);
pushOrCreate(taskAttributes,"workers","xx8238429");
pushOrCreate(taskAttributes,"workers","aa238232");
console.log(JSON.stringify(taskAttributes));

6 Comments

I didn't downvote, but I don't think it's appropriate - the conditional operator is for when you need to use the resulting expression of a conditional somewhere. A conditional operator whose resulting expression goes unused is better as an if/else statement unless you're golfing.
@CertainPerformance I think you are right. I myself never saw ternary operator like this
@CertainPerformance I personally don't see anything wrong with using a ternary operator in such a manner, it's still perfectly readable and does exactly what is intended... It's no different than using any function while ignoring the result, sometimes it just makes the most sense. Code structure-wise it may look better or more readable as an if/else statement but that could also depend on the length of the variable names too.
It smells bad to me as well, I would rather see OP's original if statement over a conditional ternary with side effects like pushing into an array.
@jonathangray my problem with it isn't that I see it as a misuse of the ternary operator, it's that it's really just a different syntax for the same logic. I was hoping for something along the lines of myobj.propName=propValue, whereby a property propName is either added or updated depending on whether or not it already exists.
|
0

Here you have another alternative, however isn't one-liner but helps to eliminate the if-else block:

function pushOrCreate(jsonObj, arrayName, newElement)
{
    jsonObj[arrayName] = jsonObj.hasOwnProperty(arrayName) ? jsonObj[arrayName] : [];
    jsonObj[arrayName].push(newElement);
}

var taskAttributesText = '{' + '"abc":"123",' + '"xyz":"hello"' + '}';

var taskAttributes = JSON.parse(taskAttributesText);
pushOrCreate(taskAttributes, "workers", "xx8238429");
pushOrCreate(taskAttributes, "workers", "aa238232");
console.log(taskAttributes);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

But, if you still wants to put it on one line, then you can do:

function pushOrCreate(jsonObj, arrayName, newElement)
{
    (jsonObj[arrayName] = jsonObj.hasOwnProperty(arrayName) ? jsonObj[arrayName] : []).push(newElement);
}

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.