admin管理员组文章数量:1026250
Think of an object array, each of them having certain array properties like versions
, targets
. I want to ungroup objects for each version
and target
.
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
{ 'name': 'c', versions: [1], targets: []}
]
Desired output for myArray
above would be:
[
{ 'name': 'a', version: 1, target: 'server1'},
{ 'name': 'a', version: 1, target: 'server2'},
{ 'name': 'a', version: 2, target: 'server1'},
{ 'name': 'a', version: 2, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server1'},
{ 'name': 'b', version: undefined, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server3'},
{ 'name': 'c', version: 1, target: undefined},
]
I pondered using nested for
/forEach
loops, but am almost pretty sure there must be a more precise and reasonable way of achieving it built-in es6 functions or so. And that's what I'm asking for.
Think of an object array, each of them having certain array properties like versions
, targets
. I want to ungroup objects for each version
and target
.
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
{ 'name': 'c', versions: [1], targets: []}
]
Desired output for myArray
above would be:
[
{ 'name': 'a', version: 1, target: 'server1'},
{ 'name': 'a', version: 1, target: 'server2'},
{ 'name': 'a', version: 2, target: 'server1'},
{ 'name': 'a', version: 2, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server1'},
{ 'name': 'b', version: undefined, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server3'},
{ 'name': 'c', version: 1, target: undefined},
]
I pondered using nested for
/forEach
loops, but am almost pretty sure there must be a more precise and reasonable way of achieving it built-in es6 functions or so. And that's what I'm asking for.
-
1
There isn't a native method that I know of off-the-bat: I guess that's because what you're seeing essentially is creating all possible binations of versions + targets. That would call for a basic
for
loop, and it will grow in plexity the more dimensions you have, since the more nested the loops will have to be. – Terry Commented Dec 18, 2019 at 7:39
4 Answers
Reset to default 6You could use .flatMap
:
const notEmpty = arr => arr.length ? arr : [undefined];
myArray.flatMap(({ name, versions, targets }) => notEmpty(versions).flatMap(version => notEmpty(targets).map(target => ({ name, version, target }))));
Or with more dimensions, generators get very useful:
function* cartesian(obj, key, ...keys) {
if(!key) {
yield obj;
return;
}
const { [key + "s"]: entries, ...rest } = obj;
for(const entry of (entries.length ? entries : [undefined])) {
yield* cartesian({ [key]: entry, ...rest }, ...keys);
}
}
myArray.flatMap(it => cartesian(it, "version", "target"))
You can use reduce
method:
const result = myArray.reduce((a, {name, versions, targets}) => {
versions.forEach((el, ind) => {
a.push({name, version: versions[ind], target: targets[ind]})
});
targets.forEach((el, ind) => {
a.push({name, version: versions[ind], target: targets[ind]})
});
return a;
}, []);
An example:
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
{ 'name': 'c', versions: [1], targets: []}
]
const result = myArray.reduce((a, {name, versions, targets}) => {
versions.forEach((el, ind) => {
a.push({name, version: versions[ind], target: targets[ind]})
});
targets.forEach((el, ind) => {
a.push({name, version: versions[ind], target: targets[ind]})
});
return a;
}, []);
console.log(result);
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2'] },
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3'] },
{ 'name': 'c', versions: [1], targets: [] }
]
const reducer = (acc, current) => {
const { name, versions, targets } = current;
for (let i = 0; i < versions.length; i++) {
acc.push({ name, version: versions[i], target: targets[i] })
}
for (let i = 0; i < targets.length; i++) {
acc.push({ name, version: versions[i], target: targets[i] })
}
return acc;
}
const ungroup = array => array.reduce(reducer, [])
console.log(ungroup(myArray))
We can Un group the objects in the following way
const rows = [
{
"groupId": "ff686b1c-0d83-4e9e-ac0e-edd4ed7a1579",
"clientName": "Apple",
"Id": 110117,
"manageFunds": [
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea53",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
},
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea54",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
}
],
"size": 2,
"bulkUploadErrorMessage": ""
},
{
"groupId": "ff686b1c-0d83-4e9e-ac0e-edd4ed7a1589",
"clientName": "Mango",
"Id": 110118,
"manageFunds": [
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea55",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
},
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea56",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
}
],
"size": 2,
"bulkUploadErrorMessage": ""
},
{
"groupId": "ff686b1c-0d83-4e9e-ac0e-edd4ed7a1599",
"clientName": "Orange",
"Id": 110119,
"manageFunds": [
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea57",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
},
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea58",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
},
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea59",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
}
],
"size": 3,
"bulkUploadErrorMessage": ""
}
]
const mergeMF = input => {
const initObj = []
input.forEach(rootItem => {
const { Id, clientName, manageFunds } = rootItem
const groupId = rootItem.groupId
manageFunds.forEach(subItem => {
const newSubItem = {
...subItem,
accountId: subItem.accountId,
Id: Id,
clientName: clientName,
groupId: groupId,
}
initObj.push({
checked: false,
data: newSubItem,
isCollapsed: false,
validationErrors: subItem.errorMessages
})
})
})
return initObj
}
console.log(mergeMF(rows))
Think of an object array, each of them having certain array properties like versions
, targets
. I want to ungroup objects for each version
and target
.
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
{ 'name': 'c', versions: [1], targets: []}
]
Desired output for myArray
above would be:
[
{ 'name': 'a', version: 1, target: 'server1'},
{ 'name': 'a', version: 1, target: 'server2'},
{ 'name': 'a', version: 2, target: 'server1'},
{ 'name': 'a', version: 2, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server1'},
{ 'name': 'b', version: undefined, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server3'},
{ 'name': 'c', version: 1, target: undefined},
]
I pondered using nested for
/forEach
loops, but am almost pretty sure there must be a more precise and reasonable way of achieving it built-in es6 functions or so. And that's what I'm asking for.
Think of an object array, each of them having certain array properties like versions
, targets
. I want to ungroup objects for each version
and target
.
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
{ 'name': 'c', versions: [1], targets: []}
]
Desired output for myArray
above would be:
[
{ 'name': 'a', version: 1, target: 'server1'},
{ 'name': 'a', version: 1, target: 'server2'},
{ 'name': 'a', version: 2, target: 'server1'},
{ 'name': 'a', version: 2, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server1'},
{ 'name': 'b', version: undefined, target: 'server2'},
{ 'name': 'b', version: undefined, target: 'server3'},
{ 'name': 'c', version: 1, target: undefined},
]
I pondered using nested for
/forEach
loops, but am almost pretty sure there must be a more precise and reasonable way of achieving it built-in es6 functions or so. And that's what I'm asking for.
-
1
There isn't a native method that I know of off-the-bat: I guess that's because what you're seeing essentially is creating all possible binations of versions + targets. That would call for a basic
for
loop, and it will grow in plexity the more dimensions you have, since the more nested the loops will have to be. – Terry Commented Dec 18, 2019 at 7:39
4 Answers
Reset to default 6You could use .flatMap
:
const notEmpty = arr => arr.length ? arr : [undefined];
myArray.flatMap(({ name, versions, targets }) => notEmpty(versions).flatMap(version => notEmpty(targets).map(target => ({ name, version, target }))));
Or with more dimensions, generators get very useful:
function* cartesian(obj, key, ...keys) {
if(!key) {
yield obj;
return;
}
const { [key + "s"]: entries, ...rest } = obj;
for(const entry of (entries.length ? entries : [undefined])) {
yield* cartesian({ [key]: entry, ...rest }, ...keys);
}
}
myArray.flatMap(it => cartesian(it, "version", "target"))
You can use reduce
method:
const result = myArray.reduce((a, {name, versions, targets}) => {
versions.forEach((el, ind) => {
a.push({name, version: versions[ind], target: targets[ind]})
});
targets.forEach((el, ind) => {
a.push({name, version: versions[ind], target: targets[ind]})
});
return a;
}, []);
An example:
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2']},
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3']},
{ 'name': 'c', versions: [1], targets: []}
]
const result = myArray.reduce((a, {name, versions, targets}) => {
versions.forEach((el, ind) => {
a.push({name, version: versions[ind], target: targets[ind]})
});
targets.forEach((el, ind) => {
a.push({name, version: versions[ind], target: targets[ind]})
});
return a;
}, []);
console.log(result);
const myArray = [
{ 'name': 'a', versions: [1, 2], targets: ['server1', 'server2'] },
{ 'name': 'b', versions: [], targets: ['server1', 'server2', 'server3'] },
{ 'name': 'c', versions: [1], targets: [] }
]
const reducer = (acc, current) => {
const { name, versions, targets } = current;
for (let i = 0; i < versions.length; i++) {
acc.push({ name, version: versions[i], target: targets[i] })
}
for (let i = 0; i < targets.length; i++) {
acc.push({ name, version: versions[i], target: targets[i] })
}
return acc;
}
const ungroup = array => array.reduce(reducer, [])
console.log(ungroup(myArray))
We can Un group the objects in the following way
const rows = [
{
"groupId": "ff686b1c-0d83-4e9e-ac0e-edd4ed7a1579",
"clientName": "Apple",
"Id": 110117,
"manageFunds": [
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea53",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
},
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea54",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
}
],
"size": 2,
"bulkUploadErrorMessage": ""
},
{
"groupId": "ff686b1c-0d83-4e9e-ac0e-edd4ed7a1589",
"clientName": "Mango",
"Id": 110118,
"manageFunds": [
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea55",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
},
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea56",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
}
],
"size": 2,
"bulkUploadErrorMessage": ""
},
{
"groupId": "ff686b1c-0d83-4e9e-ac0e-edd4ed7a1599",
"clientName": "Orange",
"Id": 110119,
"manageFunds": [
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea57",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
},
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea58",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
},
{
"accountId": "eb9e38a8-2e0e-46c2-b50a-fa5c7c18ea59",
"address": {
"address1": "",
"city": "",
"state": "",
"zipcode": "",
"country": ""
}
}
],
"size": 3,
"bulkUploadErrorMessage": ""
}
]
const mergeMF = input => {
const initObj = []
input.forEach(rootItem => {
const { Id, clientName, manageFunds } = rootItem
const groupId = rootItem.groupId
manageFunds.forEach(subItem => {
const newSubItem = {
...subItem,
accountId: subItem.accountId,
Id: Id,
clientName: clientName,
groupId: groupId,
}
initObj.push({
checked: false,
data: newSubItem,
isCollapsed: false,
validationErrors: subItem.errorMessages
})
})
})
return initObj
}
console.log(mergeMF(rows))
本文标签: How to ungroup an object array based on multiple array properties in JavascriptStack Overflow
版权声明:本文标题:How to ungroup an object array based on multiple array properties in Javascript - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745630844a2160155.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论