下划线 - 使用 _.map() 转换数组

underscore - transform an array with _.map()

我有一个多维对象数组,需要将其转换为不同的数组。我确信 _.map() 是我所需要的。之前没有使用过它,我在遍历数组以提取正确的值时遇到了问题。给出这个简化的例子:

[
   {
      "08/25/2015":[
         {
            "source":"someSource0",
            "name":"someName0",
            "stuff":"-6.728479",
            "stuffValue":"14.862200",
            "amount":"-100.00"
         },
         {
            "notNeeded0":-100,
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "08/26/2015":[
         {
            "source":"someSource1",
            "name":"someName1",
            "stuff":"-9.496676",
            "stuffValue":"10.530000",
            "amount":"-100.00"
         },
         {
            "notNeeded0":-100,
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "08/27/2015":[
         {
            "source":"someSource2",
            "name":"someName2",
            "stuff":"-9.469697",
            "stuffValue":"10.560000",
            "amount":"-100.00"
         },
         {
            "notNeeded0":-100,
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "08/28/2015":[
         {
            "source":"someSource3",
            "name":"someName3",
            "stuff":"-1.731841",
            "stuffValue":"10.570000",
            "amount":"-18.24"
         },
         {
            "source":"someSource4",
            "name":"someName4",
            "stuff":"-2.628939",
            "stuffValue":"31.100000",
            "amount":"-81.76"
         },
         {
            "notNeeded0":-100,
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "notNeeded1":-400,
      "notNeeded2":"-400.00"
   }
]

我需要将其转换为如下结构:

[
   {
      "date":"08/27/2015",
      "detail":[
         {
            "source":"someSource2",
            "name":"someName2",
            "stuff":"-9.469697",
            "stuffValue":"10.560000",
            "amount":"-100.00",
            "subtotal":"-100.00"
         }
      ]
   },
   {
      "date":"08/28/2015",
      "detail":[
         {
            "source":"someSource3",
            "name":"someName3",
            "stuff":"-1.731841",
            "stuffValue":"10.570000",
            "amount":"-18.24",
            "subtotal":"-100.00"
         },
         {
            "source":"someSource4",
            "name":"someName4",
            "stuff":"-2.628939",
            "stuffValue":"31.100000",
            "amount":"-81.76",
            "subtotal":"-100.00"
         }
      ]
   }
]

如有需要,欢迎随时提问。感谢您的协助。

编辑:此代码不适用于基于网络的使用。因此,没有必要提及 Web 和浏览器兼容性。而且,我使用下划线库来简化循环等使用纯 JS 会变得非常丑陋的任务。希望澄清意图。

使用内置 .filter, .map and .splice:

var modified = original.filter(function only_nested_arrays(obj) {
  var keys = Object.keys(obj)
  return keys.length === 1 && Array.isArray(obj[keys[0]])
}).map(function transform(obj) {
  var date = Object.keys(obj)[0],
      inner_array = obj[date],
      subtotal = inner_array.splice(-1)[0].subtotal
  inner_array.forEach(function(obj_inner) {
    obj_inner.subtotal = subtotal
  })
  return {date: date, detail: inner_array}
})

console.log(JSON.stringify(modified, null, 2))

但要注意浏览器的兼容性(请参阅 polyfill 的链接以使其在 IE8 或更低版本上运行)。如果您想测试,可运行的代码会提示结果:

"use strict"
var original = [
  {
    "08/25/2015":[
      {
        "source":"someSource0",
        "name":"someName0",
        "stuff":"-6.728479",
        "stuffValue":"14.862200",
        "amount":"-100.00"
      },
      {
        "notNeeded0":-100,
        "subtotal":"-100.00"
      }
    ]
  },
  {
    "08/26/2015":[
      {
        "source":"someSource1",
        "name":"someName1",
        "stuff":"-9.496676",
        "stuffValue":"10.530000",
        "amount":"-100.00"
      },
      {
        "notNeeded0":-100,
        "subtotal":"-100.00"
      }
    ]
  },
  {
    "08/27/2015":[
      {
        "source":"someSource2",
        "name":"someName2",
        "stuff":"-9.469697",
        "stuffValue":"10.560000",
        "amount":"-100.00"
      },
      {
        "notNeeded0":-100,
        "subtotal":"-100.00"
      }
    ]
  },
  {
    "08/28/2015":[
      {
        "source":"someSource3",
        "name":"someName3",
        "stuff":"-1.731841",
        "stuffValue":"10.570000",
        "amount":"-18.24"
      },
      {
        "source":"someSource4",
        "name":"someName4",
        "stuff":"-2.628939",
        "stuffValue":"31.100000",
        "amount":"-81.76"
      },
      {
        "notNeeded0":-100,
        "subtotal":"-100.00"
      }
    ]
  },
  {
    "notNeeded1":-400,
    "notNeeded2":"-400.00"
  }
]

var modified = original.filter(function only_nested_arrays(obj) {
  var keys = Object.keys(obj)
  return keys.length === 1 && Array.isArray(obj[keys[0]])
}).map(function transform(obj) {
  var date = Object.keys(obj)[0],
      inner_array = obj[date],
      subtotal = inner_array.splice(-1)[0].subtotal
  inner_array.forEach(function(obj_inner) {
    obj_inner.subtotal = subtotal
  })
  return {date: date, detail: inner_array}
})

alert(JSON.stringify(modified, null, 2))

使用 _.filter_.map_.chain 这就是它的样子。

var transformed = _.chain(data).filter(function (obj) {
    var keys = _.keys(obj);
    // only allow where obj has only one key & the value is an array
    // consider replacing this with a check to see if the key is a date which should be more appropriate
    return keys.length === 1 && _.isArray(obj[keys[0]]);
}).map(function (obj) {
    var date     = _.keys(obj)[0];
    var details  = obj[date];
    var subtotal = details.splice(-1)[0].subtotal; // get the last obj from array destructively
    details      = _.map(details, function (detail) {
        detail.subtotal = subtotal; // append the subtotal to all the remaining detail objects
        return detail
    });
    return {
        date   : date,
        details: details
    }
}).value();

我建议您使用 Aprillion 的回答中所示的本机函数,这样您就可以避免整个 chain() & 然后 value() 从包装对象获取实际值的用法。要求复杂一点可以用下划线