【问题标题】:replace or push object in array using underscore使用下划线替换或推送数组中的对象
【发布时间】:2015-05-18 19:39:23
【问题描述】:

我有一个带有新数据的对象和一个带有已保存数据的数组。如果来自 newData 的 cnName 已经存在于 cnData 数组中的 savedData 中,那么 savedData 中的那个对象应该被替换为 newData.cnData[0] 对象。如果它不存在,那么数据应该被推送到savedData中的cnData数组中

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"
    }
  }]
}]

我正在使用下划线

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)
        }
    })
}

这不起作用的原因是因为在第二个 _.each() 语句中。如果 cnName 在 savedData 中不存在,它将为已在 savedData 中的每个对象推送一次 newData。因此,如果 savedData 中已经有 2 个保存的对象,那么 newData 将被推送 2 次​​p>

你可以在这个 plunker 中看到控制台日志表明 newData 被推送了两次

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

我的两个问题是

  1. 有没有更简洁的下划线方式?
  2. 有没有办法阻止 _.each() 继续循环?

【问题讨论】:

  • 您似乎只想执行对象的递归合并? Lodash 有一个 [_.merge](https://lodash.com/docs#merge) 函数可以完成你想要的(他们还有很多其他库也可以做到这一点。
  • 你不能停止_.each,但你可以改用_.any。返回 true 停止

标签: javascript arrays underscore.js


【解决方案1】:

您可以使用 findIndex 查找第一个匹配的索引,如果没有找到则更新。

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];
        }
    }
}

注意:要在 try catch 块中停止每次迭代,并在所需的断点处抛出自定义错误

【讨论】:

  • 我喜欢这个解决方案,因为它删除了嵌套循环
  • 实际上并没有。循环在那里,但代码更干净,就像你问的那样,优点是函数在找到第一个索引后返回,这比遍历整个数组更有效。我看到您将数据存储在数组 [{groupName, data}] 之类的东西中,这很好,但是您可以使用对象而不是数组,并且会更加快速和高效,并且它将删除代码中的一个循环。
【解决方案2】:

您是否考虑过在第二个_.each 上循环通过newData.cnData

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)
        }
    })
}

【讨论】:

    猜你喜欢
    • 2021-01-06
    • 2023-03-28
    • 2015-05-13
    • 1970-01-01
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 2021-08-14
    • 2017-03-14
    相关资源
    最近更新 更多