如何将选择的对象属性提取到新创建的具有数组类型的属性中?

时间:2021-12-08 15:11:59

I have an JS collection (array of objects with few properties).

我有一个JS集合(具有很少属性的对象数组)。

let xyz = [{
    categoryId: 1,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 2,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 3,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
}]

How to transform such collection using LODASH to the following structure (added values property as an array of values coming from 'value' and 'value2':

如何使用LODASH将此类集合转换为以下结构(添加值属性作为来自“value”和“value2”的值数组):

let abc = [{
        categoryId: 1,
        categoryName: 'Test',
        programId: 112,
        programName: 'Program Test',
        values: [5050,1000]
    },
    ...
    ]

4 个解决方案

#1


3  

You need to transform your array using basic map operation. Using lodash:

您需要使用基本的映射操作来转换数组。使用lodash:

let abc = _.map(xyz, function(el) {
    return {
        categoryId: el.categoryId,
        categoryName: el.categoryName,
        programId: el.programId,
        programName: el.programName,
        values: [el.value, el.value2]
    };
});

But I would rather follow "You Dont Need Lodash" trend here by using Array.prototype.map function

但是我更愿意使用Array.prototype跟随“您不需要Lodash”的趋势。map函数

#2


2  

If you look for some flexibility, and don't know all the properties your objects might have, but want to merge any value* property values together, then you could maybe find inspiration in this ES6 code:

如果您寻找一些灵活性,并且不知道您的对象可能拥有的所有属性,但是希望将任何值*属性值合并在一起,那么您可能会在这个ES6代码中找到灵感:

let res = xyz.map( o => Object.assign({}, 
    ...Object.keys(o).map(key => !key.test(/^value\d*$/) && ({ [key]: o[key]})),
    { values: Object.keys(o).filter(key => key.test(/^value\d*$/)).map(key => o[key]) }
));

let xyz = [{
    categoryId: 1,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 2,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 3,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
}];

let res = xyz.map( o => Object.assign({}, 
    ...Object.keys(o).map(key => !/^value\d*$/.test(key) && ({ [key]: o[key]})),
    { values: Object.keys(o).filter(key => /^value\d*$/.test(key)).map(key => o[key]) }
));

console.log(res);
.as-console-wrapper { max-height: 100% !important; top: 0; }

If the order of the values is important, then inject a sort in the chain, just before the final .map().

如果值的顺序很重要,那么在最后的.map()之前在链中注入排序。

Lodash

With lodash it could look like this (sticking to ES5 code this time):

有了lodash,它看起来就像这样(这一次坚持ES5代码):

var res = _.map(xyz, function (o) {
    return _.set(
        _.omitBy(o, function (v, key) { return /^value\d*$/.test(key) }),
        'values', 
        _.values(_.pickBy(o, function (v, key) { 
            return /^value\d*$/.test(key)
        }))
    );
});

#3


1  

you can do it with _.merge

可以用_.merge来实现

var res = _.map(xyz, function(item) {
    return _.merge(
        {}, // to avoid xyz mutations
        _.omit(item, ['value', 'value2']), // remove useless keys
        {values: _.at(item, ['value', 'value2'])} // get needed values
    );
});

#4


0  

I added together all the properties that start with "value", just in case.

我将所有以“值”开头的属性加在一起,以防万一。

let xyz = [{
    categoryId: 1,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 2,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 3,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
}]

let abc = _.map(xyz, function (obj) {
  var valuesKeys = _.filter(_.keys(obj), function (key) {
    return key.indexOf('value') === 0;
  });
  let result = _.omit(obj, valuesKeys);
  result.values = _.reduce(_.values(_.pick(obj, valuesKeys)), _.add);
  return result;
});

console.log(abc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

#1


3  

You need to transform your array using basic map operation. Using lodash:

您需要使用基本的映射操作来转换数组。使用lodash:

let abc = _.map(xyz, function(el) {
    return {
        categoryId: el.categoryId,
        categoryName: el.categoryName,
        programId: el.programId,
        programName: el.programName,
        values: [el.value, el.value2]
    };
});

But I would rather follow "You Dont Need Lodash" trend here by using Array.prototype.map function

但是我更愿意使用Array.prototype跟随“您不需要Lodash”的趋势。map函数

#2


2  

If you look for some flexibility, and don't know all the properties your objects might have, but want to merge any value* property values together, then you could maybe find inspiration in this ES6 code:

如果您寻找一些灵活性,并且不知道您的对象可能拥有的所有属性,但是希望将任何值*属性值合并在一起,那么您可能会在这个ES6代码中找到灵感:

let res = xyz.map( o => Object.assign({}, 
    ...Object.keys(o).map(key => !key.test(/^value\d*$/) && ({ [key]: o[key]})),
    { values: Object.keys(o).filter(key => key.test(/^value\d*$/)).map(key => o[key]) }
));

let xyz = [{
    categoryId: 1,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 2,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 3,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
}];

let res = xyz.map( o => Object.assign({}, 
    ...Object.keys(o).map(key => !/^value\d*$/.test(key) && ({ [key]: o[key]})),
    { values: Object.keys(o).filter(key => /^value\d*$/.test(key)).map(key => o[key]) }
));

console.log(res);
.as-console-wrapper { max-height: 100% !important; top: 0; }

If the order of the values is important, then inject a sort in the chain, just before the final .map().

如果值的顺序很重要,那么在最后的.map()之前在链中注入排序。

Lodash

With lodash it could look like this (sticking to ES5 code this time):

有了lodash,它看起来就像这样(这一次坚持ES5代码):

var res = _.map(xyz, function (o) {
    return _.set(
        _.omitBy(o, function (v, key) { return /^value\d*$/.test(key) }),
        'values', 
        _.values(_.pickBy(o, function (v, key) { 
            return /^value\d*$/.test(key)
        }))
    );
});

#3


1  

you can do it with _.merge

可以用_.merge来实现

var res = _.map(xyz, function(item) {
    return _.merge(
        {}, // to avoid xyz mutations
        _.omit(item, ['value', 'value2']), // remove useless keys
        {values: _.at(item, ['value', 'value2'])} // get needed values
    );
});

#4


0  

I added together all the properties that start with "value", just in case.

我将所有以“值”开头的属性加在一起,以防万一。

let xyz = [{
    categoryId: 1,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 2,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
},
{
    categoryId: 3,
    categoryName: 'Test',
    programId: 112,
    programName: 'Program Test',
    value: 5050,
    value2: 1000
}]

let abc = _.map(xyz, function (obj) {
  var valuesKeys = _.filter(_.keys(obj), function (key) {
    return key.indexOf('value') === 0;
  });
  let result = _.omit(obj, valuesKeys);
  result.values = _.reduce(_.values(_.pick(obj, valuesKeys)), _.add);
  return result;
});

console.log(abc);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>