lodash将对象数组转换为单个数组键和多个值数组

时间:2016-11-16 06:06:09

标签: javascript arrays node.js underscore.js lodash

我需要传输一些具有太多键值对的数据。 由于键是相似的,我不想用每个对象传输它们。

考虑我有以下数据:

[
    {
        x:11,
        y:12
    },{
        x:21,
        y:22
    },{
        x:31,
        y:32
    },{
        x:41,
        y:42
    }
];

我需要最终输出为
[ [x,y],[[11,12],[21,22],[31,32],[41,42]] ]
[ [x,y],[11,12],[21,22],[31,32],[41,42] ]

另一方面,我应该可以转换回原来的格式。 如果能够处理某些对象中的附加键

,那将会很棒

我认为我已经看到了lodash或下划线函数用于接近/类似的东西,但我现在无法找到它。

注意:我不知道密钥是什么

5 个答案:

答案 0 :(得分:1)

使用Array#reduce

var arr = [{
  x: 11,
  y: 12
}, {
  x: 21,
  y: 22
}, {
  x: 31,
  y: 32
}, {
  x: 41,
  y: 42
}];
var keys = Object.keys(arr[0]);
var op = arr.reduce(function(a, b) {
  var arr = keys.reduce(function(x, y) {
    return x.concat([b[y]]);
  }, [])
  return a.concat([arr]);
}, [keys]); //If all the objects are having identical keys!
console.log(JSON.stringify(op));

答案 1 :(得分:1)

更简洁的做法: [编辑:添加了将其转换回来的功能]

function convert(arr) {
  var retArr = [ [/* keys (retArr[0]) */], [/* values (retArr[1]) */] ]
  arr.forEach(function(obj){
    // create new array for new sets of values
    retArr[1].push([])

    // put all of the keys in the correct array
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        // does the key exist in the array yet?
        if (retArr[0].indexOf(key) === -1) {
          retArr[0].push(key)  
        }

        // get last index of retArr[1] and push on the values
        retArr[1][retArr[1].length - 1].push(obj[key])
      }
    }
  })

  return retArr
}


function reConvert(arr) {
  var retArr = []

  var keys = arr[0]

  arr[1].forEach(function(itemArr){
    var obj = {}
    itemArr.forEach(function(item, i){
      obj[keys[i]] = item
    })
    retArr.push(obj)
  })

  return retArr
}

var objArr = [
    {
        x:11,
        y:12
    },{
        x:21,
        y:22
    },{
        x:31,
        y:32
    },{
        x:41,
        y:42
    }
]

var arrFromObj = convert(objArr)
var objFromArr = reConvert(arrFromObj)

console.log(arrFromObj)
console.log(objFromArr)

答案 2 :(得分:1)

使用Underscore的解决方案。

首先弄清楚键是什么:

var keys = _.chain(data)
    .map(_.keys)
    .flatten()
    .uniq()
    .value();

然后映射数据以选出每个键的值:

var result = [
    keys, 
    _.map(data, item => _.map(keys, key => item[key]))
];

然后又回来了:

var thereAndBackAgain = _.map(result[1], item => _.omit(_.object(result[0], item), _.isUndefined));

Lodash的object版本为zipObjectomit使用谓词为omitBy

var thereAndBackAgain = _.map(result[1], item => _.omitBy(_.zipObject(result[0], item), _.isUndefined));



var data = [
    {
        x:11,
        y:12,
        aa: 9
    },{
        x:21,
        y:22
    },{
        x:31,
        y:32,
        z: 0
    },{
        x:41,
        y:42
    }
];

var keys = _.chain(data)
	.map(_.keys)
	.flatten()
	.uniq()
	.value();

var result = [
	keys, 
	_.map(data, item => _.map(keys, key => item[key]))
];


var thereAndBackAgain = _.map(result[1], item => _.omit(_.object(result[0], item), _.isUndefined));

console.log(result)
console.log(thereAndBackAgain)

<script src="
https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
&#13;
&#13;
&#13;

答案 3 :(得分:0)

Lodash v4.17.1

修改原件

var modifiedOriginal = _.chain(original)
    .map(_.keys)
    .flatten()
    .uniq()
    .thru(function(header){
        return _.concat(
            [header],
            _.map(original, function(item) {
                return _.chain(item)
                    .defaults(_.zipObject(
                        header, 
                        _.times(_.size(header), _.constant(undefined))
                     ))
                     .pick(header)
                     .values()
                     .value()
            })
         );  
     })
     .value();

修改回原版(按键顺序不是 担保)

var backToOriginal = _.map(_.tail(modified), function(item) { 
     return _.chain(_.head(modified))
         .zipObject(item)
         .transform(function(result, val, key) {
             if (!_.isUndefined(val)) {
                 result[key] = val;
             }
          })
          .value();
 });

JSFiddle代码Apple Affiliate Program

答案 4 :(得分:0)

在ES6中,您可以通过Object.values()Object.keys()来减少它。您可以使用 this.Invoke(new MethodInvoker(OpenForm),new object[] { Keys.F12, Keys.Alt }); private void OpenForm(Keys keyPressed, Keys modifier) { --------------------------- } Array.prototype.map()

的组合来恢复它

Array.prototype.reduce()