【问题标题】:Dynamically removing multiple key/value pairs from an object从对象中动态删除多个键/值对
【发布时间】:2015-06-20 11:41:56
【问题描述】:

假设我有一个对象数组。我不想要某些键/值。删除一个键/值对的传统方法是使用delete,如下所示:

for (var i = 0; i < tracks.length; i++) {
  delete tracks[i]["currency"];
  ...
}

我要拉入的物品可能有 30 多对。有没有办法可以说明我想要哪些配对并删除所有其他配对?因此,例如在这个对象数组中,我只想保留trackNamekindprice

var tracks = [{
    trackNumber: "01",
    trackName: "Track 1",
    trackDuration: "5:35",
    kind: "song",
    currency: "USD",
    price: 1.29
}, {
    trackNumber: "02",
    trackName: "Track 2",
    trackDuration: "5:15",
    kind: "song",
    currency: "USD",
    price: 1.29
}, {
    trackNumber: "03",
    trackName: "Track 3",
    trackDuration: "5:07",
    kind: "song",
    currency: "USD",
    price: 1.29
}, {
    trackNumber: "04",
    trackName: "Track 4",
    trackDuration: "0:16",
    kind: "song",
    currency: "USD",
    price: 1.29
}, {
    trackNumber: "05",
    trackName: "Track 5",
    trackDuration: "5:35",
    kind: "song",
    currency: "USD",
    price: 1.29
}];

【问题讨论】:

  • 为什么不直接循环删除?
  • 你需要为你创建一个函数,它会(取决于)返回一个新对象
  • 为什么不使用.map() 来遍历数组。将你想要的值作为对象返回并替换变量tracks

标签: javascript arrays json object key-value


【解决方案1】:

我能提供的最简单的解决方案:

/**
 * Returns new collection which items contains only specified properties
 * @param {Array} collection of items
 * @param {Array} properties to keep
 */

function keepCollectionProperties(collection, properties) {
    return collection.map(function(item) {
        var newItem = {}
        for(var i = 0, prop; prop = properties[i]; i++)
            if (typeof item[prop] !== 'undefined')
                newItem[prop] = item[prop]
        return newItem
    })
}

var tracks = [{
    trackNumber: "01",
    trackName: "Track 1",
    trackDuration: "5:35",
    kind: "song",
    currency: "USD",
    price: 1.29
}, {
    trackNumber: "02",
    trackName: "Track 2",
    trackDuration: "5:15",
    kind: "song",
    currency: "USD",
    price: 1.29
}, {
    trackNumber: "03",
    trackName: "Track 3",
    trackDuration: "5:07",
    kind: "song",
    currency: "USD",
    price: 1.29
}, {
    trackNumber: "04",
    trackName: "Track 4",
    trackDuration: "0:16",
    kind: "song",
    currency: "USD",
    price: 1.29
}, {
    trackNumber: "05",
    trackName: "Track 5",
    trackDuration: "5:35",
    kind: "song",
    currency: "USD",
    price: 1.29
}];

var output = keepCollectionProperties(tracks, ['trackName', 'kind', 'price'])
document.write(JSON.stringify(output))

注意:避免使用delete,它会改变对象的“形状”并损害性能。尽可能使用item.prop = null。我的函数返回新集合,所以没有必要,但如果您打算再次填充新集合,最好将不需要的道具设置为null

【讨论】:

    【解决方案2】:

    这是我的建议,因为我觉得它更优雅:

    // create new array of objects from old one
    var fixed = jQuery.map(tracks, function(element, index){
        return {"trackName": element.trackName, "kind": element.kind, "price": element.price};
    }); 
    // delete old array   
    tracks = null;
    

    【讨论】:

      【解决方案3】:

      不确定这是否是您想要的,但它会遍历列表,并返回仅包含给定键的相同列表。 keys 是一个键数组。

      function LimitArray(keys, list){
          var returnArr = [];
          for (var i in list){
             var row = {};
             for (key in list[i]){
                row[key] = list[i][key];
             }
             returnArr.push(row);
          }
          return returArr;
      }
      

      你也可以用其他几种方式来修改原始列表,但我不确定这是否是你特别想要的,所以我只是返回了一个新列表。

      如果你想改变原来的,你可以这样做:

      var select = ["a","b"]
      list.map(function(val,index, array)
         {
         var keys = Object.keys(val);
         for (var key in keys){
            if(-1 == select.indexOf(keys[key]])  delete val[keys[key]];
         }}.bind(this));
      

      我相信也应该做需要做的事情。它将遍历列表,并删除所有不在选择中的键。

      【讨论】:

        【解决方案4】:

        一个自我描述的解决方案:

        // what you want to keep:
        var want_to_keep = ['trackName', 'kind', 'price'];
        
        // loop trough every main element of tracks:
        for (var i=0; i<tracks.length; i++)
            // now go trough every element of the current track:
            for (var key in tracks[i])
                // check if the current track key is wanted:
                if (want_to_keep.indexOf(key) < 0)
                    delete tracks[i][el];
        

        【讨论】:

          【解决方案5】:

          遍历数组并从每个对象中保留您想要的内容。

          var keep = ['trackName', 'kind', 'price'];
          
          for(var i = 0;i < tracks.length; i++){
          
              for(var key in tracks[i]){
                  if(keep.indexOf(key) === -1)delete tracks[i][key];
              }
          
          }
          

          【讨论】:

          • 使用查找表而不是数组 keep={trackName:1, kind:1, price:1}; 执行起来会更快,然后您可以使用简单的 if(keep[key]){ 而不是 indexOf()
          • 在第二个for-loop 的条件下,它到底在评估什么?我很困惑数组的索引号如何等于-1。
          • js 使用-1 作为数组中不存在的所有元素的索引。
          • @CarlEdwards indexOf` 如果在key 中找不到-1,则返回keep
          • @WashingtonGuedes: 不,delete 很危险,因为它不会 删除该索引...
          【解决方案6】:

          你介意使用下划线 ".pick(object, *keys) " , ".omit(object, *keys) " 并将新对象推入新数组。

          【讨论】:

            猜你喜欢
            • 2019-07-11
            • 2021-06-20
            • 2014-09-06
            • 1970-01-01
            • 2020-06-04
            • 1970-01-01
            • 1970-01-01
            • 2020-01-20
            • 1970-01-01
            相关资源
            最近更新 更多