Remove 'value' key from nested array of objects - javascript

I got an array like this:
rows: [
[
{ title: 'Test', value: 1 },
{ title: 'Test2', value: 2 },
{ title: 'Test3', value: 3 },
],
[
{ title: 'Test4', value: 4 },
{ title: 'Test5', value: 5 },
],
[
{ title: 'Test6', value: 6 },
{ title: 'Test7', value: 7 },
]
]
Now I'd like to unset the key value in each nested object.
At the moment I am doing:
rows.map(function(fields){
return fields.map(function(field){
field.value = '';
return field;
})
});
Do you see a better way to do this?

function deleteKeyFromObject(inputObject) {
for (let[currentObjectKey,currentObjectValue] of Object.entries(inputObject)) {
if (currentObjectKey === 'value') {
delete inputObject.value;
} else if (Array.isArray(currentObjectValue)) {
deleteObjectFromArray(currentObjectValue);
} else if (typeof currentObjectValue === 'object') {
deleteKeyFromObject(currentObjectValue);
}
}
;
}
function deleteObjectFromArray(inputArray) {
for (let currentIndex = 0; currentIndex < inputArray.length; currentIndex++) {
let currentElement = inputArray[currentIndex];
if (Array.isArray(currentElement)) {
deleteObjectFromArray(currentElement);
} else if (typeof currentElement === 'object') {
deleteKeyFromObject(currentElement);
}
}
;
}
var data1 = {
rows: [[{
title: 'Test',
value: 1
}, {
title: 'Test2',
value: 2
}, {
title: 'Test3',
value: 3
}, ], [{
title: 'Test4',
value: 4
}, {
title: 'Test5',
value: 5
}, ], [{
title: 'Test6',
value: 6
}, {
title: 'Test7',
value: 7
}, ]]
}
deleteKeyFromObject(data1);
console.log(data1);

Probably not modifying existing objects could be a better practice:
rows = rows.map(fields => {
return fields.map(field => {
return {...field, value: ''};
})
});

You can use delete to explicitly remove a property and its value. No map needed:
var ob = {foo:'bar',fizz:'buzz'};
console.log(ob); // Object { foo: "bar", fizz: "buzz" }
delete ob.fizz;
console.log(ob); // Object { foo: "bar" }

Related

How to construct an array of object to unique array of object

I have an array of object like this
let data =
[
{
text: 'label'
},
{
text: 'username'
},
{
text: 'category'
},
{
text: 'book'
},
{
text: 'john'
},
{
text: 'education'
},
{
text: 'car'
},
{
text: 'doe'
},
{
text: 'automotive'
},
{
text: 'shoes'
},
{
text: 'cena'
},
{
text: 'fashion'
},
]
and my expect array of objects
let result =
[
{
label: 'book',
username: 'john',
category: 'education'
},
{
label: 'car',
username: 'doe',
category: 'automotive'
},
{
label: 'shoes',
username: 'cena',
category: 'fashion'
},
]
Just a simple for loop is probably the clearest. Here storing each object in a temp variable to avoid having to access the end of the result array every iteration, and abstracting the size into a variable.
let data = [{ text: 'label' }, { text: 'username' }, { text: 'category' }, { text: 'book' }, { text: 'john' }, { text: 'education' }, { text: 'car' }, { text: 'doe' }, { text: 'automotive' }, { text: 'shoes' }, { text: 'cena' }, { text: 'fashion' },];
const size = 3;
const result = [];
for (let temp, i = size; i < data.length; i++) {
if (i % size === 0) {
result.push(temp = {});
}
temp[data[i % size].text] = data[i].text;
}
console.log(result)
How about a switch-case with a modulo % operator to check for the current key:
const transformData = (data) => {
let result = [];
let tmpObj = {};
data.forEach((element, idx) => {
switch (idx % 3) {
case 0:
tmpObj["label"] = element.text;
break;
case 1:
tmpObj["username"] = element.text;
break;
case 2:
result.push({ ...tmpObj,
category: element.text
});
tmpObj = {};
break;
default:
break;
}
});
return result;
};
console.log(transformData(getSampleData()));
function getSampleData() {
return [{
text: 'label'
},
{
text: 'username'
},
{
text: 'category'
},
{
text: 'book'
},
{
text: 'john'
},
{
text: 'education'
},
{
text: 'car'
},
{
text: 'doe'
},
{
text: 'automotive'
},
{
text: 'shoes'
},
{
text: 'cena'
},
{
text: 'fashion'
},
];
}
According to your data,the top 3 records are property name,others are data,so we can use Array.slice() to get the property names
Then we can use Array.reduce() to convert the left data
let keys = data.slice(0,3).map(v => v.text)
let result = data.slice(3).reduce((a,c,i) =>{
let key = keys[i%3]
if(i%keys.length ==0){
let obj = {}
obj[key] = c.text
a.push(obj)
}else{
a.at(-1)[key]=c.text
}
return a
},[])
console.log(result)
let data =
[
{
text: 'label'
},
{
text: 'username'
},
{
text: 'category'
},
{
text: 'book'
},
{
text: 'john'
},
{
text: 'education'
},
{
text: 'car'
},
{
text: 'doe'
},
{
text: 'automotive'
},
{
text: 'shoes'
},
{
text: 'cena'
},
{
text: 'fashion'
},
]
let keys = Object.values(data.slice(0,3)).map(v => v.text)
let result = data.slice(3).reduce((a,c,i) =>{
let key = keys[i%3]
if(i%keys.length ==0){
let obj = {}
obj[key] = c.text
a.push(obj)
}else{
a.at(-1)[key]=c.text
}
return a
},[])
console.log(result)

How to group object inside array

Here is what I have
[
{
typeProgramId: {
name: 'type1',
},
title: 'test1',
},
{
typeProgramId: {
name: 'type1',
},
subTypeProgramId: [{
name: 'sub1',
}],
title: 'test2',
},
{
typeProgramId: {
name: 'type2',
},
title: 'test3',
},
{
typeProgramId: {
name: 'type2',
},
subTypeProgramId: {
name: 'sub2',
},
title: 'test4',
}
]
First I want to group typeProgramId if the title have the same typeProgramId I want to push title into array by each typeProgramId but If the data have typeProgramId and subTypeProgram Id I want to group subtypeProgramId in typeProgramId too. if not empty subtypeProgramId I want to push it in array title inside subtypeProgram Id. I try to use lodash groupBy and many way but it still did not work.
Here is what I want
{
typeProgramId: [{
name: 'type1',
title: [
'test1',
],
subTypeProgramId: {
name: sub1,
title: [
'test2'
]
}
}, {
name: 'type2',
title: [
'test3',
],
subTypeProgramId: [{
name: sub1,
title: [
'test4'
]
}
}]
}
what I do now
let result = _.groupBy(getProgram, function(data) {
return data.typeProgramId
})
result = _.map(result, function(group, data) {
// I think in here I must groupBy subTypeProgramId again
// the data return all string not object after group
return {
typeProgramId: data,
titile: group,
}
})
Please check the below code. I have used reduce function of Array. It produces the expected result.
function updateMem(mem, prgIndex, val){
if(prgIndex < 0) {
mem.typeProgramId.push({});
prgIndex = mem.typeProgramId.length - 1;
}
mem.typeProgramId[prgIndex].name = val.typeProgramId.name;
if(val.subTypeProgramId){
mem.typeProgramId[prgIndex].subTypeProgramId = Object.assign({}, mem.typeProgramId[prgIndex].subTypeProgramId || {}, {"name" : val.subTypeProgramId.name, "title": []});
mem.typeProgramId[prgIndex].subTypeProgramId.title.push(val.title);
} else {
mem.typeProgramId[prgIndex].title = (mem.typeProgramId[prgIndex].title ? mem.typeProgramId[prgIndex].title : []);
mem.typeProgramId[prgIndex].title.push(val.title);
}
};
arr.reduce((mem, val) => {
var prgIndex = mem.typeProgramId.findIndex((p) => p.name === val.typeProgramId.name);
updateMem(mem, prgIndex, val);
return mem;
}, {typeProgramId: []});

How to get the value of each node of the tree structure

An array of nested arrays and objects, each node has a unique value, finding a value on this data, how to get the value on each node?
const opts = [
{
value: '01',
children: [
{ value: '0198' },
{ value: '0195', children: [{ value: '09977' }] }
]
},
{
value: '02',
children: [
{ value: '01986' },
{
value: '0195',
children: [
{ value: '09978', children: [{ value: '09864' }, { value: '90876' }] }
]
}
]
}
];
const code = '90876';
// expected get an array ['02','0195','09978','90876']
U could use a function to walk over the object structure recursively like described here:
const opts = [
{
value: '01',
children: [
{ value: '0198' },
{ value: '0195', children: [{ value: '09977' }] }
]
},
{
value: '02',
children: [
{ value: '01986' },
{
value: '0195',
children: [
{ value: '09978', children: [{ value: '09864' }, { value: '90876' }] }
]
}
]
}
];
function eachRecursive(obj, cb) {
for (var k in obj) {
if (typeof obj[k] == "object" && obj[k] !== null)
eachRecursive(obj[k], cb);
else
cb(obj[k]);
}
}
let results = [];
eachRecursive(opts, val => results.push(val));
console.log(results);
but not sure what you mean with your comment: // expected get an array ['02','0195','0997','90876'] can your explain why you expect that?
you can use a dfs algo
function dfs(o, target){
if(o.value == target) return [target];
if(!o.children) return false;
let path;
o.children.find(x=>path=dfs(x, target));
if(path){
return [o.value].concat(path);
}
};
const opts = [
{
value: '01',
children: [
{ value: '0198' },
{ value: '0195', children: [{ value: '09977' }] }
]
},
{
value: '02',
children: [
{ value: '01986' },
{
value: '0195',
children: [
{ value: '09978', children: [{ value: '09864' }, { value: '90876' }] }
]
}
]
}
];
let path;
opts.find(x=>path=dfs(x, '90876'))
console.log(path);
const opts = [
{
value: '01',
children: [
{ value: '0198' },
{ value: '0195', children: [{ value: '09977' }] }
]
},
{
value: '02',
children: [
{ value: '01986' },
{
value: '0195',
children: [
{ value: '09978', children: [{ value: '09864' }, { value: '90876' }] }
]
}
]
}
];
console.log(opts[1].value)
console.log(opts[1].children[1].value)
console.log(opts[1].children[1].children[0].value)
console.log(opts[1].children[1].children[0].children[1].value)

compare array of objects and remove specific item

arr1 = [
{
name: "will",
value: "1"
},
{
name: "nelson",
value: "3"
}
];
and
arr2 = [
{
name: "will",
value: 1,
submenu: [
{
name: "ralph",
value: 2
}
]
}
]
then remove ralph from the second array. i already created a function who do it but just check the first element and not verify the submenu.
comparador(arrSecundario) {
return (arrAtual) => {
return arrSecundario.filter(function (other) {
return other.value === arrAtual.value;
}).length !== 0;
};
}
this.arr2.filter(this.comparador(this.arr1));
Need to map array after filter. You can do like this and can also add "prop === 'submenu'" for specifically checking submenu inner array only.
var arr1 = [
{
name: "will",
value: "1"
},
{
name: "nelson",
value: "3"
}
];
var arr2 = [
{
name: "will",
value: 1,
submenu: [
{
name: "ralph",
value: 2
},
// {
// name: "nelson",
// value: 3
// }
]
}
];
function filterComparador(arrSecundario) {
return (arrAtual) => {
return arrSecundario.filter((other) => {
return other.value == arrAtual.value;
}).length != 0;
};
}
function mapComparador(arrSecundario) {
return (arrAtual) => {
Object.keys(arrAtual).forEach((prop) => {
if (Array.isArray(arrAtual[prop])) {
let propValue = arrAtual[prop].filter(this.filterComparador(arrSecundario));
if (propValue.length > 0) {
arrAtual[prop] = propValue.map(this.mapComparador(this.arrSecundario));
} else {
delete arrAtual[prop];
}
}
});
return arrAtual;
};
}
var manipulatedArray = this.arr2.filter(this.filterComparador(this.arr1))
.map(this.mapComparador(this.arr1));
console.log(manipulatedArray);

Merge objects from two arrays in one

I have one question about merge objects in array. The biggest problem is how to save this array structure after merger these arrays, because if I use .push() iterate after these array I receive one big array. Look on my data:
[
[
{ name: '1' },
{ name: '2' },
{ name: '3' },
],
[
{ name: '4' },
{ name: '5' },
{ name: '6' },
]
]
and
[
[
{ correct: false },
{ correct: true },
{ correct: false },
],
[
{ correct: true },
{ correct: false },
{ correct: false },
]
]
And my point is how merge these two array, to the one array in form like
[
[
{ name: '1', correct: false },
{ name: '2', correct: true },
{ name: '3', correct: false },
],
[
{ name: '4', correct: true },
{ name: '5', correct: false },
{ name: '6', correct: false },
]
]
I tried following loop but I receive one big array, but I need two array
for(i in nameArray) {
for(j in nameArray[i]){
var mergeObj = Object.assign(nameArray,correctArray[j]) //I get undefned
correctArray.push(nameArray[i][j])
}
}
You're close, but you have arrays of arrays of objects, so you need correctArray[i][j]
const nameArray = [
[{ name: '1' },{ name: '2' },{ name: '3' }],
[{ name: '4' },{ name: '5' },{ name: '6' }]
];
const correctArray = [
[{ correct: false },{ correct: true },{ correct: false }],
[{ correct: true },{ correct: false },{ correct: false }]
];
nameArray.forEach((a, i) =>
a.forEach((o, j) => Object.assign(o, correctArray[i][j]))
);
console.log(nameArray);
Here I used .forEach(), which is nicer than using for-in on arrays. The objects in the nameArray are being mutated, so that's your result. You can instead use .map() calls and add an empty object at the start of Object.assign if you don't want to mutate.
const nameArray = [
[{ name: '1' },{ name: '2' },{ name: '3' }],
[{ name: '4' },{ name: '5' },{ name: '6' }]
];
const correctArray = [
[{ correct: false },{ correct: true },{ correct: false }],
[{ correct: true },{ correct: false },{ correct: false }]
];
const result = nameArray.map((a, i) =>
a.map((o, j) => Object.assign({}, o, correctArray[i][j]))
);
console.log(result);
For a new independent array, you could use Array#reduce and build the new object in the matrix.
var array1 = [[{ name: '1' }, { name: '2' }, { name: '3' }], [{ name: '4' }, { name: '5' }, { name: '6' }]],
array2 = [[{ correct: false }, { correct: true }, { correct: false }], [{ correct: true }, { correct: false }, { correct: false }]],
result = [array1, array2].reduce((r, a) =>
(a.forEach((b, i) =>
(r[i] = r[i] || [], b.forEach((c, j) =>
Object.assign(r[i][j] = r[i][j] || {}, c)))), r), []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's another version that's blown out a little bit, and shows an example of how to handle a degree of nesting in the case of a more complex dataset.
const nameArray = [
[
{ name: '1' },
{ name: '2' },
{ name: '3' },
],
[
{ name: '4' },
{ name: '5' },
{ name: '6' },
]
];
const correctArray = [
[
{ correct: false },
{ correct: true },
{ correct: false },
],
[
{ correct: true },
{ correct: false },
{ correct: false },
]
];
var resultArray = []
function each(arr, fn){
let len = arr.length, i = -1
while(++i < len){ fn(arr[i], i) }
}
function addToArray(target, source){
each(source, (elem, index) => {
if(!target[index]){
let newElem = elem.length ? [] : {}
target[index] = newElem
}
if(elem.length){
addToArray(target[index], elem)
} else {
let keys = Object.keys(elem)
each(keys, key => {
if(target[index][key]) console.warn(`Key ${key} already exists, overwriting`)
target[index][key] = elem[key]
})
}
})
}
addToArray(resultArray, nameArray)
addToArray(resultArray, correctArray)
console.log(JSON.stringify(resultArray, null, 2))
I believe that the best approach to your problem it is a recursive function. Something similar to this one:
var a = [
[
{ name: '1' },
{ name: '2' },
{ name: '3' },
],
[
{ name: '4' },
{ name: '5' },
{ name: '6' },
]
]
var b = [
[
{ correct: false },
{ correct: true },
{ correct: false },
],
[
{ correct: true },
{ correct: false },
{ correct: false },
]
]
var c = [
[
{ hello: "world" }
]
];
function mergeRecursive(x,y){
/**
* Ignore functions
*/
if( x instanceof Function ) {
x = undefined;
}
if( y instanceof Function ) {
y = undefined;
}
/**
* Ignore undefineds
*/
if( x == undefined ) {
return y;
}
if( y == undefined ) {
return x;
}
/**
* Get the keys and remove duplicated
*/
var kx = Object.keys(x).filter( (k) => ! ( x[k] instanceof Function ) );
var ky = Object.keys(y).filter( (k) => ! ( y[k] instanceof Function ) );
var ks = kx.concat(
ky.filter(
(e) => kx.indexOf(e) == -1
)
);
/**
* Define the type of the result
*/
var result;
if (x instanceof Array && y instanceof Array ) {
result = [];
ks = ks.map( (k) => 1 * k ); // cast to number
} else {
result = {};
}
/**
* Create the merge object recursively
*/
ks.forEach( (k) => result[k] = mergeRecursive(x[k],y[k]) );
return result;
}
var example1 = mergeRecursive(a,b);
console.log("example 1");
console.log(example1);
var example2 = mergeRecursive(example1,c);
console.log("example 2");
console.log(example2);
let arr1 = [[ { name: '1' }, { name: '2' }, { name: '3' }],[{ name: '4' }, { name: '5' }, { name: '6' }]]
let arr2 = [[{ correct: false },{ correct: true },{ correct: false }],[{ correct: true },{ correct: false },{ correct: false }]]
let arr3 = arr1.map((ele,ind)=>{
return ele.map((e,i)=>Object.assign(e,arr2[ind][i]))
})

Categories