繁体   English   中英

如何使用纯Javascript访问最深层的双重嵌套数组/对象?

[英]How to access innermost levels of doubly nested arrays/objects using plain Javascript?

我怀疑答案很简单,但是我搜索了该网站和其他网站,但没有找到一个。 我有一个双重嵌套的数据结构,无法弄清楚如何在最内层进行迭代。 我猜想它可能涉及到forEach()或map()方法,但我尝试过的任何方法都没有。

背景:我已经简化了该问题的数据。 数据(粘贴在下面)存储在包含2个零售商店对象的数组中。 每个商店对象都有一个visits属性,其值是一组visit对象。 每次访问(对象)都由访问日期标识(假设在日期B最多可以有1次访问存储A)。 每个访问对象都包含一个values属性,其值是该访问时进行的交易(购买或退货)数组。 在实际的完整数据中,每个商店的每个日期的交易数量变化很大。

我需要帮助的任务:(a)将属性key重命名为visitDate ,(b)将属性values重命名为transactions ,(c)删除8个冗余属性(从storeIDstoreVisitDate ),但保留actiondollarAmount属性,以及(d)将属性dollarAmount重命名为dollars

非常感激任何的帮助。 谢谢。

 [
   {
     "storeName": "Ye Olde Candy Shoppe",
     "address": "1313 Vampire Lane, Cityville NY 99999",
     "zipCode": "99999",
     "storeSize": "large",
     "visits": [
       {
         "key": "5/3/12",
         "values": [
           {
             "storeID": "53454447",
             "storeName": "Ye Olde Candy Shoppe",
             "city": "Cityville",
             "building": "1313",
             "street": "Vampire Lane",
             "zipcode": "99999",
             "storeSize": "large",
             "storeVisitDate": "5/3/12",
             "action": "Return",
             "dollarAmount": "65.43"
           },
           {
             "storeID": "53454447",
             "storeName": "Ye Olde Candy Shoppe",
             "city": "Cityville",
             "building": "1313",
             "street": "Vampire Lane",
             "zipcode": "99999",
             "storeSize": "large",
             "storeVisitDate": "5/3/12",
             "action": "Purchase",
             "dollarAmount": "12.43"
           },
           {
             "storeID": "53454447",
             "storeName": "Ye Olde Candy Shoppe",
             "city": "Cityville",
             "building": "1313",
             "street": "Vampire Lane",
             "zipcode": "99999",
             "storeSize": "large",
             "storeVisitDate": "5/3/12",
             "action": "Purchase",
             "dollarAmount": "5.43"
           }
         ]
       },
       {
         "key": "12/31/12",
         "values": [
           {
             "storeID": "53454447",
             "storeName": "Ye Olde Candy Shoppe",
             "city": "Cityville",
             "building": "1313",
             "street": "Vampire Lane",
             "zipcode": "99999",
             "storeSize": "large",
             "storeVisitDate": "12/31/12",
             "action": "Purchase",
             "dollarAmount": "2.53"
           }
         ]
       },
       {
         "key": "1/24/13",
         "values": [
           {
             "storeID": "53454447",
             "storeName": "Ye Olde Candy Shoppe",
             "city": "Cityville",
             "building": "1313",
             "street": "Vampire Lane",
             "zipcode": "99999",
             "storeSize": "large",
             "storeVisitDate": "1/24/13",
             "action": "Return",
             "dollarAmount": "2.53"
           },
           {
             "storeID": "53454447",
             "storeName": "Ye Olde Candy Shoppe",
             "city": "Cityville",
             "building": "1313",
             "street": "Vampire Lane",
             "zipcode": "99999",
             "storeSize": "large",
             "storeVisitDate": "1/24/13",
             "action": "Return",
             "dollarAmount": "64.22"
           }
         ]
       }
     ]
   },
   {
     "storeName": "Mike's Bikes",
     "address": "2626 Aardvark Circle, Townsville NY 88888",
     "zipCode": "88888",
     "storeSize": "small",
     "visits": [
       {
         "key": "8/8/14",
         "values": [
           {
             "storeID": "24335234",
             "storeName": "Mike's Bikes",
             "city": "Townsville",
             "building": "2626",
             "street": "Aardvark Circle",
             "zipcode": "88888",
             "storeSize": "small",
             "storeVisitDate": "8/8/14",
             "action": "Purchase",
             "dollarAmount": "443.55"
           },
           {
             "storeID": "24335234",
             "storeName": "Mike's Bikes",
             "city": "Townsville",
             "building": "2626",
             "street": "Aardvark Circle",
             "zipcode": "88888",
             "storeSize": "small",
             "storeVisitDate": "8/8/14",
             "action": "Purchase",
             "dollarAmount": "34"
           },
           {
             "storeID": "24335234",
             "storeName": "Mike's Bikes",
             "city": "Townsville",
             "building": "2626",
             "street": "Aardvark Circle",
             "zipcode": "88888",
             "storeSize": "small",
             "storeVisitDate": "8/8/14",
             "action": "Purchase",
             "dollarAmount": "12.32"
           }
         ]
       },
       {
         "key": "10/3/15",
         "values": [
           {
             "storeID": "24335234",
             "storeName": "Mike's Bikes",
             "city": "Townsville",
             "building": "2626",
             "street": "Aardvark Circle",
             "zipcode": "88888",
             "storeSize": "small",
             "storeVisitDate": "10/3/15",
             "action": "Purchase",
             "dollarAmount": "233.1"
           },
           {
             "storeID": "24335234",
             "storeName": "Mike's Bikes",
             "city": "Townsville",
             "building": "2626",
             "street": "Aardvark Circle",
             "zipcode": "88888",
             "storeSize": "small",
             "storeVisitDate": "10/3/15",
             "action": "Return",
             "dollarAmount": "44.99"
           }
         ]
       }
     ]
   }
 ]

没错! 您可以使用.map()完成大部分操作。 新的ES6标准使这一切变得更加容易,并且使用以下功能,您甚至都不会修改任何原始数据!:

array.map(store => {
  //return a new object that takes all the store info, then reassigns the visits key in a new object
  return Object.assign({}, store, {
    //map over visits, and reassign the key key to visitDate
    visits: store.visits.map(({ key: visitDate, values }) => {
      return {
        //return an obj with visit date
        visitDate,
        // do destructuring again to create objects of action,dollars
        transactions: values.map(({ action, dollarAmount: dollars }) => ({ action, dollars }))
      };
    })
  });
});

此处是jsFiddle上的工作示例 -只需打开JS控制台即可查看转换后的数据集)

以下是有关解决方案的几点说明:

  • 即使您的数据有更多的键(在您粘贴的样本中)也可以使用(您提到这是一个简化的集合,因此可能很重要)
  • 它使用“映射”很多,而不是手动遍历数组。 我发现它更具可读性。

     // Go over all stores stores.map(function(store) { // In each store, go over all visits. store.visits.map(function(visit) { // In each visit, copy 'key' to 'visitDate' // and 'values' to 'transactions'. // Then delete old names ('key' and 'values'). visit.visitDate = visit.key; visit.transactions = visit.values; delete visit.key; delete visit.values; // For each transaction, replace it with a simple // map with only 'action' and 'dollars'. visit.transactions = visit.transactions.map(function(tx) { return { action: tx.action, dollars: tx.dollarAmount }; }); }); }); 

请注意,在IE9和更高版本中支持map()

要重命名属性,您可以创建一个具有相同值的新属性,然后delete旧属性。

您可以将其用于所有部分,但是在您的结构上,通过使用map()创建新的“优化”交易并将其分配给新的transactions属性,将b,c,d组合在一起看起来更加巧妙。

 // (I put this in a function so the logic can be at the top of the snippet) function fixData(stores) { // loop stores and their visits for (var iStore = 0; iStore < stores.length; iStore++) { var store = stores[iStore]; for (var iVisit = 0; iVisit < store.visits.length; iVisit++) { var visit = store.visits[iVisit]; // (a) rename property key to visitDate // add a new property with the same value then delete the old property visit.visitDate = visit.key; delete visit.key; // (b) rename property values to transactions // add a new property with the same value then delete the old property // (c) delete the 8 redundant properties (from storeID to storeVisitDate) // we could delete keys but quicker to map a new object // (d) rename property dollarAmount to dollars. // just give the new object property a different name visit.transactions = visit.values.map(function(trans) { return { action: trans.action, dollars: trans.dollarAmount } }); delete visit.values; } } console.log(stores); } var stores = [{ "storeName": "Ye Olde Candy Shoppe", "address": "1313 Vampire Lane, Cityville NY 99999", "zipCode": "99999", "storeSize": "large", "visits": [{ "key": "5/3/12", "values": [{ "storeID": "53454447", "storeName": "Ye Olde Candy Shoppe", "city": "Cityville", "building": "1313", "street": "Vampire Lane", "zipcode": "99999", "storeSize": "large", "storeVisitDate": "5/3/12", "action": "Return", "dollarAmount": "65.43" }, { "storeID": "53454447", "storeName": "Ye Olde Candy Shoppe", "city": "Cityville", "building": "1313", "street": "Vampire Lane", "zipcode": "99999", "storeSize": "large", "storeVisitDate": "5/3/12", "action": "Purchase", "dollarAmount": "12.43" }, { "storeID": "53454447", "storeName": "Ye Olde Candy Shoppe", "city": "Cityville", "building": "1313", "street": "Vampire Lane", "zipcode": "99999", "storeSize": "large", "storeVisitDate": "5/3/12", "action": "Purchase", "dollarAmount": "5.43" }] }, { "key": "12/31/12", "values": [{ "storeID": "53454447", "storeName": "Ye Olde Candy Shoppe", "city": "Cityville", "building": "1313", "street": "Vampire Lane", "zipcode": "99999", "storeSize": "large", "storeVisitDate": "12/31/12", "action": "Purchase", "dollarAmount": "2.53" }] }, { "key": "1/24/13", "values": [{ "storeID": "53454447", "storeName": "Ye Olde Candy Shoppe", "city": "Cityville", "building": "1313", "street": "Vampire Lane", "zipcode": "99999", "storeSize": "large", "storeVisitDate": "1/24/13", "action": "Return", "dollarAmount": "2.53" }, { "storeID": "53454447", "storeName": "Ye Olde Candy Shoppe", "city": "Cityville", "building": "1313", "street": "Vampire Lane", "zipcode": "99999", "storeSize": "large", "storeVisitDate": "1/24/13", "action": "Return", "dollarAmount": "64.22" }] }] }, { "storeName": "Mike's Bikes", "address": "2626 Aardvark Circle, Townsville NY 88888", "zipCode": "88888", "storeSize": "small", "visits": [{ "key": "8/8/14", "values": [{ "storeID": "24335234", "storeName": "Mike's Bikes", "city": "Townsville", "building": "2626", "street": "Aardvark Circle", "zipcode": "88888", "storeSize": "small", "storeVisitDate": "8/8/14", "action": "Purchase", "dollarAmount": "443.55" }, { "storeID": "24335234", "storeName": "Mike's Bikes", "city": "Townsville", "building": "2626", "street": "Aardvark Circle", "zipcode": "88888", "storeSize": "small", "storeVisitDate": "8/8/14", "action": "Purchase", "dollarAmount": "34" }, { "storeID": "24335234", "storeName": "Mike's Bikes", "city": "Townsville", "building": "2626", "street": "Aardvark Circle", "zipcode": "88888", "storeSize": "small", "storeVisitDate": "8/8/14", "action": "Purchase", "dollarAmount": "12.32" }] }, { "key": "10/3/15", "values": [{ "storeID": "24335234", "storeName": "Mike's Bikes", "city": "Townsville", "building": "2626", "street": "Aardvark Circle", "zipcode": "88888", "storeSize": "small", "storeVisitDate": "10/3/15", "action": "Purchase", "dollarAmount": "233.1" }, { "storeID": "24335234", "storeName": "Mike's Bikes", "city": "Townsville", "building": "2626", "street": "Aardvark Circle", "zipcode": "88888", "storeSize": "small", "storeVisitDate": "10/3/15", "action": "Return", "dollarAmount": "44.99" }] }] }]; fixData(stores); 

如果我们假设您的数组称为arr,我建议:

arr.forEach(function(currentValue, index, array) {
   currentValue.visits = currentValue.visits.map(function(currentValue, index, array) {
      currentValue.visitDate = currentValue.key;
      delete currentValue.key;
      currentValue.transactions = currentValue.values.map(function(currentValue, index, array) {
         currentValue = {action: currentValue.action, dollars: currentValue.dollarAmount};
         return currentValue;
      });
      delete currentValue.values;
      return currentValue;
   });
});

好吧,由于这是“数据”,而不是某些内存中的对象,所以我猜您是通过使用JSON.parse从JSON获得的。 (如果没有,您仍然可以通过首先使用JSON.strigify来使用此方法)

您知道JSON.parse接受用于控制此类事件的函数吗? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse

所以....

fixed=JSON.parse(dataString, function(key,value){
 if(key=="key"){this.visitDate=value;return}
 if(key=="values"){this.transactions=value;return}
 if(key=="somethingYouDontWant"){return;}
 //etc...
 return value;    
})

它纯净的javascript,没有任何库,并使用简单的地图:

 var y = x.map(function(xs){
      xs.visits = xs.visits.map(function (item){
        return {
          visitDate: item.key,
          transactions: item.values.map(function(v){
            return {
              action: v.action,
              dollars: v.dollarAmount
            };
          })
        };
      });
      return xs;
    });

Array.map()delete运算符的灵活解决方案:

var delete_props = ["storeID","storeName","city","building","street", "zipcode","storeSize", "storeVisitDate"];

 // arr is your initial array
 arr.map(function(obj){
     obj['visits'].map(function(inner_obj){
         inner_obj['visitDate'] = inner_obj['key'];
         delete inner_obj['key'];

         inner_obj['values'].map(function(values_obj){
            values_obj['dollars'] = values_obj['dollarAmount'];
            delete values_obj['dollarAmount'];

            delete_props.forEach(function(v){
                delete values_obj[v];
            });
        });
        inner_obj['transactions '] = inner_obj['values'];
        delete inner_obj['values'];

     });     
 });

这是另一种解决方案,代码非常简单,但尚未优化。

var obj = {}, key;
data.forEach(item => {
  item.visits.forEach(visit => {
    visit.visitDate = visit.key; 
    delete visit.key;
    visit.transactions = [];
    visit.values.forEach(value => {
      obj = {};
      for (key in value) {
        if (value.hasOwnProperty(key) && retain.indexOf(key) > -1) {
          obj[key] = value[key];
        }
      }
      visit.transactions.push(obj);
    });
    delete visit.values;
  });
console.log(item);
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM