2

I have one object with new data coming in and one array with data that has been saved. If cnName from newData already exists in savedData in the cnData array then that object in savedData should be replaced with newData.cnData[0] object. If it does not exists then the data should to pushed to the cnData array in savedData

newData = {
  "cnGroupName": "cnGroupName1",
  "cnData": [{
    "cnName": "cn3",
    "data": {
       "color": "blue",
       "size": "42",
       "position": "right"
    }
  }]
}

savedData = [{
  "cnGroupName": "cnGroupName1",
  "cnData": [{
    "cnName": "cn1",
    "data": {
      "color": "red",
      "size": "42",
      "position": "right"
    }
  }, {
    "cnName": "cn2",
    "data": {
      "color": "blue",
      "size": "11",
      "position": "top"
    }
  }]
}]

I am using underscore

if(savedData.length){
    _.each(savedData, function(num, i){

        if(savedData[i].cnGroupName == newData.cnGroupName ){

            _.each(savedData[i].cnData, function(num, x){


               if(savedData[i].cnData[x].cnName == newData.cnData[0].cnName){

                    // the cnName already exists in savedData so replace
                    savedData[i].cnData[x] = newData.cnData[0] 


               }else{ 
                    // the cnName  does NOT exist in savedData so push the new object to savedData
                   savedData[i].cnData.push(newData.cnData[0])
                }
            })
        }else{
            // the cnGroupName from newData is not in saveData so push newData
            savedData.push(newData)
        }
    })
}

the reason this does not work is because in the second _.each() statment. If the cnName does NOT exist in savedData it will push newData once for every object that is already in savedData. So if there are already 2 saved objects in savedData then the newData will be pushed 2 times

you can see the console logs in this plunker that the newData is being pushed twice

http://plnkr.co/edit/GkBoe0F65BCEYiFuig57?p=preview

My 2 questions are

  1. is there a cleaner way of doing this in underscore?
  2. is there a way to stop _.each() from continuing the loop ?
2
  • It seems like you just want to perform a recursive merge of the objects? Lodash has a [_.merge](https://lodash.com/docs#merge) function that would accomplish what you want (their are plenty of other libraries out do to this as well. Commented May 18, 2015 at 19:42
  • You can't stop _.each, but you can just use _.any instead. return true to stop Commented May 18, 2015 at 19:44

2 Answers 2

1

You can use findIndex to find the first matching index and update if not found.

if(savedData.length){
    var cnindex,
    index = _.findIndex(savedData, function (item) { return item.cnGroupName == newData.cnGroupName });
    if (index === -1)) {
        savedData.push(newData);
    } else {
        cnindex = _.findIndex(savedData[index].cnData, function (item) {return item.cnName == newData.cnData[0].cnName});
        if (cnindex === -1) {
            savedData[index].cnData.push(newData.cnData[0]);
        } else {
            savedData[index].cnData[cnindex] = newData.cnData[0];
        }
    }
}

Note: To stop a each iteration wrap in a try catch block and throw a custom error in the desired break point

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

2 Comments

I like this solution because it removes the nested loops
Actualy it doesn't. The loops are there but the code is cleaner like you asked, the advantage is that the function returns after the first index is found which is more efficient than go through the entire array. I see that you store your data in something like array [{groupName, data}] wich is good but you can use an object instead of an array and will be even more fast and efficient and it will remove one loop in your code.
0

Have you considered looping through newData.cnData on the second _.each?

if(savedData.length > 0){

    _.each(savedData, function(num, i){

        if(savedData[i].cnGroupName == newData.cnGroupName ){

            _.each(newData.cnData, function(num, x){
           // ^ change the subject here


               if(savedData[i].cnData[x].cnName == newData.cnData[0].cnName){

                    // the cnName already exists in savedData so replace
                    console.log("cn names are the same")
                    savedData[i].cnData[x] = newData.cnData[0] 


               }else{ 
                    // the cnName  does NOT exist in savedData so push
                    console.log("cn names are diffrent")
                   savedData[i].cnData.push(newData.cnData[0])
                }
            })
        }else{
            // the cnGroupName from newData is not in saveData so push newData
            savedData.push(newData)
        }
    })
}

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.