I am trying to change the value of object from the array but, it's not work as expected. I tried following.
const arrObj = [
{
"label": "test1",
"value": 123,
"type": "number",
"field": {
"label": "another",
"description": "abcd"
}
},
{
"label": "test2",
"value": 111,
"type": "number"
},
]
arrObj.forEach(obj => {
obj = {...obj, ...obj.field}
delete obj.field
})
console.log("after:", arrObj);
Also I found some solution that to use index but, it add index before the object.
const arrObj = [
{
"label": "test1",
"value": 123,
"type": "number",
"field": {
"label": "abcd",
"description": "abcd"
}
},
{
"label": "test2",
"value": 111,
"type": "number"
}
]
arrObj.forEach((obj, index) => {
obj[index] = {...obj, ...obj.field}
delete obj.field
})
console.log("after:", arrObj);
How can I do with forEach?
Edit:
I want to remove the field object and assign/overwrite all the property outside.
Using map and assigning the result is probably a better way of doing this, but if you want to use forEach, you need to assign to the original array inside the loop:
const arrObj = [
{
"label": "test1",
"value": 123,
"type": "number",
"field": {
"label": "another",
"description": "abcd"
}
},
{
"label": "test2",
"value": 111,
"type": "number"
},
]
arrObj.forEach(({ field, ...rest}, idx, orig) => {
orig[idx] = { ...rest, ...field }
})
console.log(arrObj);
I would use map to change an array, but you may have a reason that you wish to modify the original. You could just reassign arrObj to the output of the map.
const arrObj = [
{
"label": "test1",
"value": 123,
"type": "number",
"field": {
"label": "another",
"description": "abcd"
}
},
{
"label": "test2",
"value": 111,
"type": "number"
},
]
const newArr = arrObj.map(( obj ) => {
const {field, ...rest} = obj
return {...field, ...rest}
})
console.log("after:", newArr);
Related
I have the following Array of object using this information I want to update array of object with value:a without mutating it directly (I am able to solve it using index but I don't want to update it using index) below is the code that I have tried so far
ccategory.map((item) =>
item.id === payload.id
? {
...item,
categoryItems: item.categoryItems.map(
(catItem) => catItem.categoryItemID === payload.categoryItemID
// stuck here how should I update categorySubItems?
),
}
: item
),
const payload={
"id": "4476c379-2c4f-4454-b59e-cae2f62fdfe2",
"categorySubItemsID": "c2cba4d6-5635-4b5c-acf3-b93b4d435aa9",
"categoryItemID": "fdb0e86b-a2d9-4029-8988-9f50121794d3",
"value": "a"
}
MyJSON looks like this
const category=[
{
"id": "4476c379-2c4f-4454-b59e-cae2f62fdfe2",
"categoryName": "Car",
"categoryFields": [
{
"name": "Car Name",
"type": "text",
"categoryID": "e9da78fb-d349-4b03-9b77-e3cc0dc57d25"
},
{
"name": "Price",
"type": "number",
"categoryID": "c9e147a6-b5d1-424b-99bf-a973ce189322"
}
],
"categoryItems": [
{
"categoryItemID": "fdb0e86b-a2d9-4029-8988-9f50121794d3",
"categorySubItems": [
{
"categorySubItemsID": "c2cba4d6-5635-4b5c-acf3-b93b4d435aa9",
"value": "",
"label": "Car Name",
"type": "text",
"categoryLinkID": "e9da78fb-d349-4b03-9b77-e3cc0dc57d25"
},
{
"categorySubItemsID": "01d5e1e7-3927-42a6-ad05-7399a5895096",
"value": "",
"label": "Price",
"type": "number",
"categoryLinkID": "c9e147a6-b5d1-424b-99bf-a973ce189322"
}
]
},
{
"categoryItemID": "f13237d7-abfd-40d3-ae35-0b59ddf5734e",
"categorySubItems": [
{
"categorySubItemsID": "2af389b9-03bc-41d3-86bb-8bf324ca3cb3",
"value": "",
"label": "Car Name",
"type": "text",
"categoryLinkID": "e9da78fb-d349-4b03-9b77-e3cc0dc57d25"
},
{
"categorySubItemsID": "934ef505-72bb-4d64-adf1-2aa5e928a539",
"value": "",
"label": "Price",
"type": "number",
"categoryLinkID": "c9e147a6-b5d1-424b-99bf-a973ce189322"
}
]
}
]
},
{
"id": "9882b210-2d99-43a3-8aea-9f7d7c88eeda",
"categoryName": "Bike",
"categoryFields": [
{
"name": "Bike Name",
"type": "text",
"categoryID": "73bee24c-ef64-4798-bc37-5fe90cbc8de7"
}
],
"categoryItems": []
}
]
In your inner .map(), if catItem.categoryItemID === payload.categoryItemID matches, you can return a new object that has an updated categorySubItems, which you can update by creating a new array by mapping catItem.categorySubItems. When mapping the sub category items, if your categorySubItemsID matches the one from the payload object, you can return a new updated object with a new value set to that of payload.value, otherwise, you can keep the original item, eg:
ccategory.map((item) =>
item.id === payload.id
? {
...item,
categoryItems: item.categoryItems.map((catItem) =>
catItem.categoryItemID === payload.categoryItemID
? {
...catItem,
categorySubItems: catItem.categorySubItems.map(subCatItem =>
subCatItem.categorySubItemsID === payload.categorySubItemsID
? {...subCatItem, value: payload.value}
: subCatItem
)
}
: catItem
),
}
: item
),
As you can see, this can get quite unwieldy. That's why it's often useful to use something like useImmer(), which allows you to directly modify a "draft" state value in an immutable way while keeping your state updates mutable.
I have an object with the structure of:
[
{
"id": "NONSTOPS",
"label": "Nonstop",
"value": "no"
},
{
"id": "REWARDS",
"label": "Rewards",
"value": "no"
},
{
"id": "SEAT",
"label": "Seats",
"value": "no"
},
{
"id": "BAGS",
"label": "Bags",
"value": "no"
}
]
and an array with a structure of
["NONSTOPS", "REWARDS"]
To return
[
{
"id": "NONSTOPS",
"label": "Nonstop",
"value": "yes"
},
{
"id": "REWARDS",
"label": "Rewards",
"value": "yes"
},
{
"id": "SEAT",
"label": "Seats",
"value": "no"
},
{
"id": "BAGS",
"label": "Bags",
"value": "no"
}
]
Based on the array, it would search the object and change the value to "yes" if there exists an ID on the array.
Here's my code so far
for(let i=0; i< obj.length; i++){
for(let j = 0; j<array.length; j++){
if(obj[i].id === array[j]){
obj[i].value ='yes'
}
}
}
Something seems off about my code and I was wondering if there was an easier way to do this, maybe with a mapper of some sorts?
Can probably use a .forEach and an indexOf check on your array (just to be more concise, there's nothing wrong with your approach)
obj.forEach(o => {
if (array.indexOf(o.id) > -1) o.value = "yes";
});
You can use includes
const data = [{
"id": "NONSTOPS",
"label": "Nonstop",
"value": "no"
},
{
"id": "REWARDS",
"label": "Rewards",
"value": "no"
},
{
"id": "SEAT",
"label": "Seats",
"value": "no"
},
{
"id": "BAGS",
"label": "Bags",
"value": "no"
}
]
const lookup = ["NONSTOPS", "REWARDS"];
const reduced = data.map(d => {
return {id: d.id, label: d.label, value: lookup.includes(d.id) ? "YES" : "NO"}
});
console.log(reduced);
You can use a simple for of loop to iterate over the array of objects and then check with the built in includes function if the value exist in the flat array.
const arr = [
{
"id": "NONSTOPS",
"label": "Nonstop",
"value": "no"
},
{
"id": "REWARDS",
"label": "Rewards",
"value": "no"
},
{
"id": "SEAT",
"label": "Seats",
"value": "no"
},
{
"id": "BAGS",
"label": "Bags",
"value": "no"
}
]
const arrToCompare = ["NONSTOPS", "REWARDS"]
for (let obj of arr) {
// you can use includes to find is the value exist in the arrToCompare
if (arrToCompare.includes(obj.id)) {
// if exists then mutate it
obj.value = 'yes';
}
}
console.log(JSON.stringify(arr, null, 4));
In the question you have mentioned that you want to return the valid elements. You can use filter() for the same.
var result = obj.filter(o => (array.indexOf(o.id) > -1) );
I got stuck on a maybe simple task, but could not find any solution.
I have some JSON Data - lets say:
[{
"_id": 1,
"type": "person",
"Name": "Hans",
"WorksFor": ["3", "4"]
}, {
"_id": 2,
"type": "person",
"Name": "Michael",
"WorksFor": ["3"]
}, {
"_id": 3,
"type": "department",
"Name": "Marketing"
}, {
"_id": 4,
"type": "department",
"Name": "Sales"
}]
As I learned here it is quite simple to get all the persons and the departments they work for together using a map array for the departments.
Then I can map the corresponding department to the Person and receive something like:
[{
"_id": 1,
"type": "person",
"Name": "Hans",
"WorksFor": ["3", "4"],
"Readable": ["Marketing", "Sales"]
}, {
"_id": 2,
"type": "person",
"Name": "Michael",
"WorksFor": ["3"],
"Readable": ["Sales"]
}]
But for another interface I need the data "the other way round" e.g.
[{
"_id": 3,
"type": "department",
"Name": "Marketing",
"employees": [
"Hans", "Michael"
]
}, {
"_id": 4,
"type": "department",
"Name": "Sales",
"employees": [
"Hans"
]
}]
Is there any decent way to achieve this structure? Two days of trying didn't get me anywhere...
var data = [{ "_id": 1, "type": "person", "Name": "Hans", "WorksFor": ["3", "4"] }, { "_id": 2, "type": "person", "Name": "Michael", "WorksFor": ["3"] }, { "_id": 3, "type": "department", "Name": "Marketing" }, { "_id": 4, "type": "department", "Name": "Sales" }];
var departments = [],
persons = [];
data.forEach(e => {
if (e.type === "person") {
persons.push(e);
} else if (e.type === "department") {
departments.push(e);
e.employees = [];
}
});
departments.forEach(d => {
var workers = persons.filter(p => p.WorksFor.indexOf(d._id.toString()) > -1)
/*.map(p => p.Name)*/ // add this if you only need the name instead of the complete "person"
d.employees = d.employees.concat(workers);
});
console.log(JSON.stringify(departments, null, 4));
You can try something like this:
var data = [{ "_id": 1, "type": "person", "Name": "Hans", "WorksFor": ["3", "4"]}, { "_id": 2, "type": "person", "Name": "Michael", "WorksFor": ["3"]}, { "_id": 3, "type": "department", "Name": "Marketing"}, { "_id": 4, "type": "department", "Name": "Sales"}]
var ignoreDept = ['person'];
var result = data.reduce(function(p,c,i,a){
if(ignoreDept.indexOf(c.type) < 0){
c.employees = a.reduce(function(arr,emp){
if(emp.WorksFor && emp.WorksFor.indexOf(c._id.toString()) > -1){
arr.push(emp.Name)
}
return arr;
},[]);
p.push(c);
}
return p;
}, []);
console.log(result)
The solution using Array.prototype.filter() and Array.prototype.forEach() functions:
var data = [{ "_id": 1, "type": "person", "Name": "Hans", "WorksFor": ["3", "4"]}, { "_id": 2, "type": "person", "Name": "Michael", "WorksFor": ["3"]}, { "_id": 3, "type": "department", "Name": "Marketing"}, { "_id": 4, "type": "department", "Name": "Sales"}],
// getting separated "lists" of departments and employees(persons)
deps = data.filter(function(o){ return o.type === "department"; }),
persons = data.filter(function(o){ return o.type === "person"; });
deps.forEach(function (d) {
d['employees'] = d['employees'] || [];
persons.forEach(function (p) {
if (p.WorksFor.indexOf(String(d._id)) !== -1) { // check the `id` coincidence between the employee and the department
d['employees'].push(p.Name);
}
});
});
console.log(deps);
You could use a hash table and a single loop for each array.
Methods:
Array#reduce for iterating an array and returning the result,
Array#forEach for looping the inner array WorksFor,
Object.create(null) to generate an object without any prototypes,
some other pattern, like a closure over hash and
the use of logical OR || for checking a falsy value and taking an object as default.
hash[b] = hash[b] || { _id: b, employees: [] };
var data = [{ _id: 1, type: "person", Name: "Hans", WorksFor: [3, 4] }, { _id: 2, type: "person", Name: "Michael", WorksFor: [3] }, { _id: 3, type: "department", Name: "Marketing" }, { _id: 4, type: "department", Name: "Sales" }],
result = data.reduce(function (hash) {
return function (r, a) {
if (a.type === 'person') {
a.WorksFor.forEach(function (b) {
hash[b] = hash[b] || { _id: b, employees: [] };
hash[b].employees.push(a.Name);
});
}
if (a.type === 'department') {
hash[a._id] = hash[a._id] || { _id: b, employees: [] };
hash[a._id].type = a.type;
hash[a._id].Name = a.Name;
r.push(hash[a._id]);
}
return r;
};
}(Object.create(null)), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's a way you can get the first mapping. I've added some comments so you can follow along, and with it I hope you can find the answer to your second problem.
// First, let's get just the items in this array that identify persons
// I've called this array "data"
data.filter(x => x.type === 'person')
// Now let's map over them
.map(person =>
// We want all of the data associated with this person, so let's
// use Object.assign to duplicate that data for us
Object.assign({}, person, {
// In addition, we want to map the ID of the WorksFor array to the Name
// of the corresponding department. Assuming that the _id key is unique,
// we can due this simply by mapping over the WorksFor array and finding
// those values within the original array.
Readable: person.WorksFor.map(wfId =>
// Notice here the parseInt. This will not work without it due to
// the type difference between WorksFor (string) and _id (integer)
data.find(d => d._id === parseInt(wfId)).Name
)
})
);
var data = [{ "_id": 1, "type": "person", "Name": "Hans", "WorksFor": ["3", "4"]}, { "_id": 2, "type": "person", "Name": "Michael", "WorksFor": ["3"]}, { "_id": 3, "type": "department", "Name": "Marketing"}, { "_id": 4, "type": "department", "Name": "Sales"}];
var dep = {};
data.forEach(e => (e.type === 'person' && e.WorksFor.forEach(d => dep[d]? dep[d].push(e.Name): dep[d] = [e.Name])));
data.forEach(e => (e.type == 'department' && (e.employees = dep[e._id] || [])));
data = data.filter(e => e.type == 'department');
console.log(data);
I have 2 different object arrays which i would like to merge according to the "id" value.
So if my first array looks like this:
[
{
"id": "75318408571184",
"component": "textInput",
"index": 0,
"label": "Text",
"description": "description",
"placeholder": "placeholder",
},
{
"id": "9463537670672",
"component": "textArea",
"index": 1,
"label": "Paragraph",
"description": "description",
"placeholder": "placeholder"
}
]
and my second one looks something like this:
[
{
"id": "75318408571184",
"value": "value1"
},
{
"id": "9463537670672",
"value": "value2"
}
]
i would like to get this array of objects:
[
{
"id": "75318408571184",
"component": "textInput",
"index": 0,
"label": "Text",
"description": "description",
"placeholder": "placeholder",
"value": "value1"
},
{
"id": "9463537670672",
"component": "textArea",
"index": 1,
"label": "Paragraph",
"description": "description",
"placeholder": "placeholder",
"value": "value2"
}
]
is there a neat way to do this in angular or javascript without looping through the array?
try this:
var result = firstArray.map(function(item) {
var second = secondArray.find(function(i) {
return item.id === i.id;
});
return second ? Object.assign(item, second) : item;
});
console.log(result);
Array.prototype.map() applies function in argument on each item of firstArray and returns new array with modified values.
Object.assign() is function which copies properties of second object to the item object in the code above.
The above answers are already good. But if you want to look at some other libraries you can have a look at this .
loadash merge
var object = {
'fruits': ['apple'],
'vegetables': ['beet']
};
var other = {
'fruits': ['banana'],
'vegetables': ['carrot']
};
_.merge(object, other, function(a, b) {
if (_.isArray(a)) {
return a.concat(b);
}
});
// → { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
In plain Javascript, you can use Array.prototype.forEach() and Array.prototype.some()
var obj1 = [{ "id": "75318408571184", "component": "textInput", "index": 0, "label": "Text", "description": "description", "placeholder": "placeholder", }, { "id": "9463537670672", "component": "textArea", "index": 1, "label": "Paragraph", "description": "description", "placeholder": "placeholder" }],
obj2 = [{ "id": "75318408571184", "value": "value1" }, { "id": "9463537670672", "value": "value2" }];
obj2.forEach(function (a) {
obj1.some(function (b) {
if (a.id === b.id) {
b.value = a.value;
return true;
}
});
});
document.write('<pre>' + JSON.stringify(obj1, 0, 4) + '</pre>');
Another possibility is to build a hash table temp first and then manipulate the item directly.
var obj1 = [{ "id": "75318408571184", "component": "textInput", "index": 0, "label": "Text", "description": "description", "placeholder": "placeholder", }, { "id": "9463537670672", "component": "textArea", "index": 1, "label": "Paragraph", "description": "description", "placeholder": "placeholder" }],
obj2 = [{ "id": "75318408571184", "value": "value1" }, { "id": "9463537670672", "value": "value2" }],
temp = {};
obj1.forEach(function (a, i) {
temp[a.id] = i;
});
obj2.forEach(function (a) {
obj1[temp[a.id]].value = a.value;
});
document.write('<pre>' + JSON.stringify(obj1, 0, 4) + '</pre>');
I have 2 arrays with objects in them. I am trying to make a new array based on the information provided in the original 2 arrays. I have jQuery and Underscore available.
The 2 arrays look like the following:
var orgArray = [
{
"name": "phone",
"value": "123-456-7890"
},
{
"name": "color",
"value": "blue"
},
{
"name": "city",
"value": "San Diego"
},
{
"name": "zip",
"value": "54321"
},
{
"name": "email",
"value": "something#somewhere.com"
},
{
"name": "state",
"value": "CA"
},
{
"name": "Sale",
"value": "On Sale"
}
];
var configArray = [
{
"columns": ["phone", "city", "zip"],
"target": "phone"
},
{
"columns": ["email", "state"],
"target": "email"
}
];
If configArray[i].columns contains a string that is in orgArray[i].name then add the target property to the orgArray's object. Here is the new Array that I am trying to create:
var newArray = [
{
"name": "phone",
"value": "123-456-7890",
"target": "phone"
},
{
"name": "color",
"value": "blue"
},
{
"name": "city",
"value": "San Diego",
"target": "phone"
},
{
"name": "zip",
"value": "54321",
"target": "phone"
},
{
"name": "email",
"value": "something#somewhere.com",
"target": "email"
},
{
"name": "state",
"value": "CA",
"target": "email"
},
{
"name": "Sale",
"value": "On Sale"
}
];
Here is my current JS and a fiddle:
jsFiddle: http://jsfiddle.net/9Dv2f/
var newArray = [];
_.each(orgArray, function(element, index, list) {
_.each(configArray, function(elem, i) {
_.each(elem.columns, function (el, x) {
if (element.name === el.name) {
console.log(element.name);
newArray.push({
name: element.name,
value: element.value,
target: elem.target
});
}
});
});
});
console.log(newArray);
Using $.each() you can do:
$.each(orgArray, function(i, org){
$.each(configArray, function(j, config){
if(config.columns.indexOf(org.name) > -1){
orgArray[i].target = config.target;
}
});
});
DOCUMENTATION
You should test if the name exists in elem.column, you can do this by using the .indexOf function. The .indexOf function returns the index of the found object (starting from 0), if it isn't found it will return -1.
if(elem.columns.indexOf(element.name) > -1)
FIDDLE
Something underscore way, not sure(didn't confirmed), should work.
Copy the array and map it to updated based on your condition.
var newArray = orgArray;
_.map(newArray, function(elem){
_.each(configArray, function(elem_config, i) {
if(_.contains(elem_config, newArray.name)){
return newArray['target'] = elemconfig.target
}
}
}