Related
I need to create a combination of n array with structure of data like this
var arrayObject = [
{ name: "size", value: "small" },
{ name: "size", value: "medium" },
{ name: "size", value: "large" },
{ name: "color", value: "red" },
{ name: "color", value: "blue" },
{ name: "color", value: "green" }
]
is there any way to set an array that contain combination of the above array?
the expected output is
var result = [
[{ Name: "size:", Value: "small" }],
[{ Name: "size:", Value: "medium" }],
[{ Name: "size:", Value: "large" }],
[{ Name: "color", Value: "red" }],
[{ Name: "color:", Value: "green" }],
[{ Name: "color:", Value: "blue" }],
[{ Name: "size", Value: "small" },{ Name: "color:", Value: "red" }],
[{ Name: "size", Value: "small" },{ Name: "color:", Value: "green"}],
[{ Name: "size", Value: "small" },{ Name: "color:", Value: "blue"}],
[{ Name: "size", Value: "medium" },{ Name: "color:", Value: "red"}],
[{ Name: "size", Value: "medium" },{ Name: "color:", Value: "blue"}],
[{ Name: "size", Value: "medium" },{ Name: "color:", Value: "green"}],
[{ Name: "size", Value: "large" },{ Name: "color:", Value: "red"}],
[{ Name: "size", Value: "large" },{ Name: "color:", Value: "blue"}],
[{ Name: "size", Value: "large" },{ Name: "color:", Value: "green"}],
]
Any help would be much appreciated. thank you
This will do it:
const arrayObject = [
{ name: "size", value: "small" },
{ name: "size", value: "medium" },
{ name: "size", value: "large" },
{ name: "color", value: "red" },
{ name: "color", value: "blue" },
{ name: "color", value: "green" },
];
const sizes = arrayObject.filter((e) => e.name === "size");
const colors = arrayObject.filter((e) => e.name === "color");
const result = sizes.flatMap((size) => colors.map((color) => [size, color]));
const mergedresult = [...arrayObject, ...result];
console.log(JSON.stringify(mergedresult, null, 2));
One caveat, you need a recent JS interpreter to use flatMap (check the compatibility matrix here).
A few thoughts:
The naming of arrayObject is pretty generic. If you control that initial data structure, I would do something like I did to name it semantically, which leads to splitting it.
The output at the end is a merge of the input and the combinations, which seems strange. I'd think you'd want only the combinations, no? Because you can always merge them at any later point, but separating them later is trickier.
First make separate lists for colors and sizes. Build all possible combinations with multiple forEach loops.
const combinations = (arr) => {
const output = [];
const b = { size: [], color: [] };
arr.forEach(({ name: Name, value: Value }) => {
output.push({ Name, Value });
b[Name].push({ Name, Value });
});
b.size.forEach((size) =>
b.color.forEach((color) => output.push([{...size}, {...color}]))
);
return output;
};
var arr = [
{ name: "size", value: "small" },
{ name: "size", value: "medium" },
{ name: "size", value: "large" },
{ name: "color", value: "red" },
{ name: "color", value: "blue" },
{ name: "color", value: "green" },
];
console.log(combinations(arr))
const combinations = (arr, includeEmpty = false) => {
const groups = {};
arr.forEach(({ name: Name, value: Value }) => {
if (!groups[Name]) {
groups[Name] = includeEmpty ? [null] : [];
}
groups[Name].push({ Name, Value });
});
let output = [[]];
Object.values(groups).forEach(group => {
const temp = [];
group.forEach(item => {
output.forEach(list => temp.push(item ? list.concat(item) : list));
});
// deep copy
output = JSON.parse(JSON.stringify(temp));
});
return output;
};
var arr = [
{ name: "size", value: "small" },
{ name: "size", value: "medium" },
{ name: "size", value: "large" },
{ name: "color", value: "red" },
{ name: "color", value: "blue" },
{ name: "color", value: "green" },
{ name: "shape", value: "circle" },
{ name: "shape", value: "square" },
];
const items = combinations(arr, true);
console.log(items.length);
console.log(items);
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have got two arrays of objects . I want to filtering data based on PermissionObj.
This is coming form database. Here is arrays of sub-arrays in the permissionObj .
const PermissionObj = {
permission: [{
"books": [{
"label": "Can View",
"value": "can_view"
}]
},
{
"Journals": [{
"label": "Can View",
"value": "can_view"
},
{
"label": "Can Create",
"value": "can_create"
},
]
},
{
"deal": [{
"label": "Can update",
"value": "can_update"
},
{
"label": "Can delete",
"value": "can_delete"
},
]
}
]
}
this is static data. I want to compare this data based on PermissionObj.
const data = [{
label: "books",
value: "can_view"
},
{
label: "deal",
content: [{
value: "can_update"
}, {
value: "can_delete"
},{value:"can_view"}]
},
{
label: "Articles",
},
{
label: "Journals",
content: [{
value: "can_create"
},
{
value: "can_view"
},
{
value: "can_delete"
},
{
value: "can_edit"
},
]
}
]
I am trying filter data array of object based on PermissionObj array of objects . here is my trying code.
let permission = PermissionObj.permission
permission.filter(item=>{
// I am finding data label by using permission label.
let dataItem = data.find(index=>item[index.label])
console.log(dataItem)
})
// the problem is that I want to filtering based on value .
// if both of value is true , then show the data .
if PermissionObj value will be matched with data value . then show the data .
My accepted Output would be this format :
const data = [{
label: "books",
value: "can_view"
},
{
label: "deal",
content: [{
value: "can_update"
}, {
value: "can_delete"
}]
},
{
label: "Journals",
content: [{
value: "can_create"
},
{
value: "can_view"
},
]
}
]
First build keys from PermissionObj. Use filter on data array which label includes in keys.
const PermissionObj = {
permission: [
{
books: [
{
label: "Can View",
value: "can_view"
}
]
},
{
Journals: [
{
label: "Can View",
value: "can_view"
},
{
label: "Can Create",
value: "can_create"
}
]
},
{
deal: [
{
label: "Can update",
value: "can_update"
},
{
label: "Can delete",
value: "can_delete"
}
]
}
]
};
const data = [
{
label: "books",
value: "can_view"
},
{
label: "deal",
content: [
{
value: "can_update"
},
{
value: "can_delete"
}
]
},
{
label: "Articles"
},
{
label: "Journals",
content: [
{
value: "can_create"
},
{
value: "can_view"
}
]
}
];
const perm = {};
PermissionObj.permission.forEach(item =>
Object.entries(item).forEach(([key, values]) => {
perm[key] = values.map(x => x.value);
})
);
const updated = data
.map(item => {
const newItem = {
...item
};
if (item.content) {
newItem.content = item.content.filter(x =>
perm[item.label].includes(x.value)
);
} else if (item.value) {
newItem.value = perm[item.label].includes(item.value) ? item.value : "";
}
return newItem;
})
.filter(x => x.content || x.value);
console.log(updated);
so you can get keys of the permission array, this would give you an array of keys.since you are getting the keys of an item in an array of objects so the key would always be the first item then you can check each data item with that key
const PermissionObj = {
permission: [
{
books: [
{
label: "Can View",
value: "can_view"
}
]
},
{
Journals: [
{
label: "Can View",
value: "can_view"
},
{
label: "Can Create",
value: "can_create"
}
]
},
{
deal: [
{
label: "Can update",
value: "can_update"
},
{
label: "Can delete",
value: "can_delete"
}
]
}
]
};
const data = [
{
label: "books",
value: "can_view"
},
{
label: "deal",
content: [
{
value: "can_update"
},
{
value: "can_delete"
}
]
},
{
label: "Articles"
},
{
label: "Journals",
content: [
{
value: "can_create"
},
{
value: "can_view"
}
]
}
];
let permission = PermissionObj.permission;
let NewData = [];
permission.filter(item => {
let ObjectKeys = Object.keys(item);
let ObjKey = ObjectKeys[0];
let DATA = data.find(
dataItem => dataItem.label.toString() === ObjKey.toString()
);
NewData.push(DATA);
});
console.log(NewData);
I have got two arrays of objects. I want to filter data based on permissionObj.
This is coming from database. Here are arrays of sub-arrays in the permissionObj.
let permissionObj = [
{
"Deposit": [{
label: "can create",
value: "can_create"
},
]
},
{
"Journals": [{
label: "can create",
value: "can_create"
}]
},
{
"Dashboard": [{
label: "can view",
value: "can_view"
}]
},
]
this is static data. I want to compare this data based on permission.
const PubSidebar = [{
label: "Dashboard",
value: "can_view"
},
{
label: "OA deal",
content: [
{
label: "Deposit",
key: "Deposit",
value: "can_view"
},
{
label: "Corrections",
key: "Corrections",
value: "can_edit"
},
]
},
{
label: "Journal",
content: [{
label: "Add Journal",
key: "Journals",
value: "can_create"
},
]
},
];
Here is my PubSidebar , I need three types of filtering
- if pubSidebar array of Objects then it will be filtering based on label.For examaple, Dashboard
- if pubSidebar array of sub-array of objects, then filtering will be based label, key and value , For example, PermissionObj key: will be property name such as OA deal, Deposit, value : can_view or anything
My expected output would be :
const PubSidebar = [{
label: "Dashboard",
value: "can_view"
},
{
label: "OA deal",
content: [
{
label: "edit oadeal ",
key: "OA deal",
value: "can_edit"
},
{
label: "Deposit",
key: "Deposit",
value: "can_view"
},
]
},
{
label: "Journal",
content: [{
label: "Add Journal",
key: "Journals",
value: "can_create"
},
]
},
];
You can gain of reduce method as it allows to write complex logic and decide what should be done on each iteration of an array. I slightly edited your source data as it is hard to understand the logic of filtering.
At first, we create an object which will contain filter data. Why object? As object has O(1) to access to their keys.
const filterObject = permissionObj.reduce((a, c) => {
for (const key in c) {
a[key] = c[key];
}
return a;
},{});
Then we use reduce method to decide whether the array element is eligible to be pushed:
const result = PubSidebar.reduce((a, c)=> {
if (filterObject[c.label] && c.value
&& filterObject[c.label].some(s => s.value == c.value) ) {
a.push(c);
}
else if (c.content.some(s => filterObject[s.key]) && c.content) {
c.content = c.content.filter(f => filterObject[f.key]
&& filterObject[f.key].some(s => s.value == f.value));
a.push(c);
}
return a;
}, [])
An example:
let permissionObj = [
{
"OA deal": [{
label: "can view",
value: "can_view"
}
]
}, {
"Deposit": [{
label: "can edit",
value: "can_edit"
},
]
},
{
"Deposit": [{
label: "can_view",
value: "can_view"
},
]
},
{
"Journals": [{
label: "can create",
value: "can_create"
}]
},
{
"Dashboard": [{
label: "can view",
value: "can_view"
}]
}
];
const PubSidebar = [
{
label: "Dashboard",
value: "can_view"
},
{
label: "OA deal",
content: [
{
label: "view oadeal",
key: "OA deal",
value: "can_view"
},
{
label: "Deposit",
key: "Deposit",
value: "can_view"
},
{
label: "Corrections",
key: "Corrections",
value: "can_edit"
},
]
},
{
label: "Journal",
content: [{
label: "Add Journal",
key: "Journals",
value: "can_create"
},
]
},
];
const filterObject = permissionObj.reduce((a, c) => {
for (const key in c) {
a[key] = c[key];
}
return a;
},{});
const result = PubSidebar.reduce((a, c)=> {
if (filterObject[c.label] && c.value
&& filterObject[c.label].some(s => s.value == c.value) ) {
a.push(c);
}
else if (c.content.some(s => filterObject[s.key]) && c.content) {
c.content = c.content.filter(f => filterObject[f.key]
&& filterObject[f.key].some(s => s.value == f.value));
a.push(c);
}
return a;
}, [])
console.log(result);
I am building best employee survey project using surveyjs. When working in matrix type, I get trouble how to change text "employee1,employee2,employee3" with real name employee
see picture.
so far here is my code:
var json = {
title: "Software developer survey.",
pages: [
{
title: "Part 1",
questions: [
{
type: "matrix",
name: "Question1",
//isAllRowRequired: true,
title: "Please indicate if you agree or disagree with the following statements",
columns: [
{
value: 1,
text: "Strongly Disagree"
}, {
value: 2,
text: "Disagree"
}, {
value: 3,
text: "Neutral"
}, {
value: 4,
text: "Agree"
}, {
value: 5,
text: "Strongly Agree"
}
],
rows: [
{
value: "valueEmployee1",
text: "Employee1 ![Employee1](https://bezone.files.wordpress.com/2008/02/soeharto.jpg =50x50)"
}, {
value: "valueEmployee2",
text: "Employee2"
}, {
value: "valueEmployee3",
text: "Employee3"
}
]
},
//
]
},
thank you for your help
You can add matrix rows dynamically:
var json = {
questions: [
{
type: "matrix",
name: "score",
title: "Please score the employees in the list",
columns: [
{
value: 1,
text: "Bad"
}, {
value: 2,
text: "So-so"
}, {
value: 3,
text: "Good enough"
}, {
value: 4,
text: "Good"
}, {
value: 5,
text: "Excellent"
}
],
rows: [
]
}
]
};
window.survey = new Survey.Model(json);
var q = survey.getQuestionByName("score");
var employees = [{ id: "id1", name: "John"}, { id: "id2", name: "Ben"}, { id: "id3", name: "Chack"}]
employees.forEach(function(employee) {
q.rows.push(new Survey.ItemValue(employee.id, employee.name));
});
Here is the working sample - https://plnkr.co/edit/OMBt1n02Qc8f5znUmOHE?p=preview
I have multiple objects in an array. They each have a labelId assigned to them. If the label id is the same then I need to combine the objects by placing some of the values inside an array of the new combined object.
[
{
field: "legalName",
isOpened: false,
label: "Legal Name",
labelId: 1,
value: "John Doe"
},
{
field: "homeAddress1",
isOpened: false,
label: "Home Address",
labelId: 2,
value: "2343 Main Street"
},
{
field: "homeAddress2",
isOpened: false,
label: "Home Address",
labelId: 2,
value: "New York, NY"
}
]
What I want it to look like
[
{
isOpened: false,
label: "Legal Name",
labelId: 1,
values:
[
{field: "legalName", value: "John Doe"}
]
},
{
isOpened: false,
label: "Home Address",
labelId: 2,
values:
[
{field: "homeAddress1", value: "2343 Main Street"},
{field: "homeAddress2", value: "New York, NY"}
]
}
]
I am removing the field and value from the original object and placing it into an array of values for all objects regardless if they have the same labelId.
Code so far -
personalInfoArray.forEach(info => {
personalInfoArray.forEach(info2 => {
if ((info.labelId === info2.labelId) && (info.field !== info2.field)) {
info.values = [
{field: info.field, value: info.value},
{field: info2.field, value: info2.value}
]
}
})
})
I am looping through the same array twice in order to determine if the object has the same labelId, if success - create array. The issue is I'm not removing the properties and the other object still exists. Along with if they don't have the same labelId, nothing happens.
Thanks
This is an approach using the function Array.prototype.reduce to group the object by labelId and the function Object.values to extract the grouped objects.
let arr = [{ field: "legalName", isOpened: false, label: "Legal Name", labelId: 1, value: "John Doe" }, { field: "homeAddress1", isOpened: false, label: "Home Address", labelId: 2, value: "2343 Main Street" }, { field: "homeAddress2", isOpened: false, label: "Home Address", labelId: 2, value: "New York, NY" }],
result = Object.values(arr.reduce((a, {labelId, field, isOpened, label, value}) => {
(a[labelId] || (a[labelId] = {isOpened, label, labelId, values: []})).values.push({field, value});
return a;
}, Object.create(null)));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }