Push same multiple objects into multiple arrays - javascript

This is a follow up to Make 3 arrays correspond to each other with the first being the object name.
AFter I create my objects:
let objName = ["object1", "object2", "object3"];
let xyzArr = ["xyz1", "xyz2","xyz3"];
let theArr = [[], [], []];
objName.forEach((name, index) => {
window[name] = {
xyz: xyzArr[index],
arr: theArr[index]
};
});
I use getJSON and want to use those values to push into the array: arr[]. I have multiple objects that have the arr[] and I want to push values into all of them.
This is what I tried so far:
$.getJSON(json, result =>
{result.forEach((elem, i, array) =>
{object1.arr.push({x:elem.val1, y:elem.val2});
{object2.arr.push({x:elem.val1, y:elem.val2});
{object3.arr.push({x:elem.val1, y:elem.val2});
})
});
When I do this one by one, it works. No errors. Is there a way for me to push these same values into how many ever object[i] I have?
I tried:
$.getJSON(json, result =>
{result.forEach((elem, i, array) =>
(for let j=0; j<=5; j++) {
{object[i].arr.push({x:elem.val1, y:elem.val2});
)
})
});
When I do this I get Cannot call method 'push' of undefined.
Is there a way to do this without making my code long and bulky?

Instead of dynamically creating variables using window, you can use an array to store a collection of your objects like so:
let xyzArr = ["xyz1", "xyz2", "xyz3"];
let theArr = [[], [], []];
let objects = [];
objName.forEach((name, index) => {
objects.push({
xyz: xyzArr[index],
arr: theArr[index]
});
});
And then when adding data to each object, you can loop through it using a .forEach() on your objects array like so:
$.getJSON(json, result => {
result.forEach(elem => {
objects.forEach(obj => {
obj.arr.push({
x: elem.val1,
y: elem.val2
});
});
});
});

object[i] refers to an array named object which obviously doesn't exist.
Try this oneliner instead:
$.getJSON(json, result => result.forEach((elem, i, array) => window['object' + (i + 1)].data.push({ x: elem.val1, y: elem.val2 })));

Related

How to get data inside a Nested Array of object

const datafromback=[[{name:ravi}],[{}],[{}],[{}]]
I want to access ravi. Can anyone help me how can i see ravi in my console.with dealing with nested arrays
I not getting approach but i can use map to map through datafromback array but don't know how to get inside it
You can use 0 index
const datafromback = [[{ name: 'ravi' }], [{}], [{}], [{}]]
const dataFrom = (arr, nameRavi) => {
let result
arr.forEach((ele) => {
if (ele[0].name === nameRavi) result = ele[0].name
})
return result
}
console.log(dataFrom(datafromback, 'ravi'))
one possible way is to use flat first to remove nested array
const datafromback=[[{name:ravi}],[{}],[{}],[{}]]
const flatternArray = datafromback.flat() // [{name:ravi},{},{},{}]
flatternArray.map(item => {
console.log(item.name) //
})
you can do this :
const datafromback=[[{name:'ravi'}],[{}],[{}],[{}]]
const [{name}] = datafromback.find(data=>data.find(item=>item.name === 'ravi')?.name === 'ravi')
console.log(name)
You can create a recursive function if you have non-fixed dimensions array :
const handle = e => {
if (Array.isArray(e))
return e.map(handle)
else {
console.log(e.name)
}
}
handle(array)
Or if you know the dimensions, you can use nested for loops like so :
// example for 2 dimensions
for (let y = 0; y < array.length; y++)
for (let x = 0; x < array[y].length; x++)
console.log(array[y][x].name)
Hey so what you have above is a 2D object array. if you just want to console you can use a nested forEach to get the key value, like this.
datafromback.forEach(data => {
//this is the nested array that contains the objects
data.forEach(obj => {
//here you can access the actual object
if (obj?.name) console.log(obj.name);
});
});
this will return the value of key (name) if present ie ravi in your case.
you can do it like this
const datafromback = [[{ name: 'ravi' }], [{}], [{}], [{}]];
const names = [];
datafromback.map((items) => {
items.map((item) => {
if (item?.name) names.push(item?.name);
});
});
console.log(names);

ES6 Filtering objects by unique attribute

I've an array of errors, each error has a non-unique param attribute.
I'd like to filter the array based on whether the param has been seen before.
Something like this:
const filteredErrors = [];
let params = [];
for(let x = 0; x < errors.length; x++) {
if(!params.includes(errors[x].param)) {
params.push(errors[x].param);
filteredErrors.push(errors[x]);
}
}
But I've no idea how to do this in ES6.
I can get the unique params const filteredParams = Array.from(new Set(errors.map(error => error.param)));
but not the objects themselves.
Pretty sure this is just a weakness in my understanding of higher order functions, but I just can't grasp it
You could destrucure param, check against params and add the value to params and return true for getting the object as filtering result.
As result you get an array of first found errors of the same type.
const
params = [],
filteredErrors = errors.filter(({ param }) =>
!params.includes(param) && params.push(param));
Instead of an array you can make use of an object to keep a map of existing values and make use of filter function
let params = {};
const filteredErrors = errors.filter(error => {
if(params[error.param]) return false;
params[error.param] = true;
return true;
});
i'd probably do it like this with a reduce and no need for outside parameters:
const filteredErrors = Object.values(
errors.reduce((acc, val) => {
if (!acc[val.param]) {
acc[val.param] = val;
}
return acc;
}, {}))
basically convert it into an object keyed by the param with the object as values, only setting the key if it hasn't been set before, then back into an array of the values.
generalized like so
function uniqueBy(array, prop) {
return Object.values(
array.reduce((acc, val) => {
if (!acc[val[prop]]) {
acc[val[prop]] = val;
}
return acc;
}, {}))
}
then just do:
const filteredErrors = uniqueBy(errors, 'param');
If your param has a flag identifier if this param has been seen before then you can simply do this.
const filteredErrors = errors.filter(({ param }) => param.seen === true);
OR
const filteredErrors = errors.filter((error) => error.param.seen);
errors should be an array of objects.
where param is one of the fields of the element of array errors and seen is one of the fields of param object.
You can do it by using Array.prototype.reduce. You need to iterate through the objects in the array and keep the found params in a Set if it is not already there.
The Set.prototype.has will let you find that out. If it is not present in the Set you add it both in the Set instance and the final accumulated array, so that in the next iteration if the param is present in your Set you don't include that object:
const errors = [{param: 1, val: "err1"}, {param: 2, val: "err2"}, {param: 3, val: "err3"}, {param: 2, val: "err4"}, {param: 1, val: "err5"}];
const { filteredParams } = errors.reduce((acc, e) => {
!acc.foundParams.has(e.param) && (acc.foundParams.add(e.param) &&
acc.filteredParams.push(e));
return acc;
}, {foundParams: new Set(), filteredParams: []});
console.log(filteredParams);

lodash flatten inner array (part of object) and generate as many object based on array length

I have the following Array of Objects. I want to generate as many Objects based on inner 'Y' array length.
var arr = [{x:1,y:[1,2]},{x:2,y:[1,2]}];
Expected Output as follows
var arr = [{x:1,y:1},{x:1,y:2},{x:2,y:1},{x:2,y:2}]
Code I have tried but i could't
arr.forEach(item => {
return item.y.forEach(inner => {
return inner;
})
})
You can use flatMap() with nested map(). Use flatMap() on the main array and inside that use map() on y property of that object. return an object from inner map() function whose y property will be different and x will be the same
var arr = [{x:1,y:[1,2]},{x:2,y:[1,2]}];
const res = arr.flatMap(({x, y}) => y.map(y => ({x, y})));
console.log(res)
If you don't understand the flatMap below is the version using nested forEach
var arr = [{x:1,y:[1,2]},{x:2,y:[1,2]}];
const res = [];
arr.forEach(a => {
a.y.forEach(y => {
res.push({x: a.x, y});
})
})
console.log(res)

Array.prototype.map() returns empty item but Array.prototype.forEach() doesn't

I experience a weird behaviour from .map(). It returns an empty item whilst .forEach() doesn't.
Here's the code:
class Entry {
constructor(data) {
this.name = data[0],
this.age = data[1],
this.school = data[2]
};
get organised() {
return this.organise();
};
organise() {
const data = {
name: this.name,
school: this.school
};
return data;
}
}
const getDataForEach = (obj) => {
let r = [];
obj.forEach((i) => {
const e = new Entry(i);
r.push(e.organised);
});
return r;
};
getDataForEach(input); // return normal object array [{...}, {...}, ...]
But if I use .map(), it returns an object array with the first item is empty. The other items are the same as result from .forEach().
const getDataMap = (obj) => {
return obj.map((i) => {
const e = new Entry(i);
console.log(e) // return normal [{...}]
console.log(e.organised) // return normal {...}
return e.organised;
});
};
getDataMap(input); // return an object array with the first item empty [<1 empty item>, {...}, {...}, ...]
Have you experienced anything similar to this?
When processing a sparse array, both map and forEach() skip elements that have never been assigned or have been deleted.
The difference, though, is that map constructs the resulting array itself, while your forEach() code is pushing onto the result array. push() will never create holes in the array, since it always appends a new element at the current length, but map() can. MDN points out:
Due to the algorithm defined in the specification if the array which map was called upon is sparse, resulting array will also be sparse keeping same indices blank.
You would get a result similar to map if you changed the forEach code to use the input array indices rather than using push, e.g.
const getDataForEach = (obj) => {
let r = [];
obj.forEach((i, index) => {
const e = new Entry(i);
r[index] = e.organised;
});
return r;
};

Looping through objects in array

I'm looping trough 2-dimensional objects inside an array. I currently do this the following way:
My array looks like this
var myarray = [
0: {
child_obj: {}
}
1: {//etc}
];
And I loop through the second-level objects like this
jQuery.each(myarray, function(i, first) {
jQuery.each(first.child_obj, function(j, second) {
//do stuff
}
});
});
So that's a loop inside a loop. It works fine, but it doesn't look very neat and I feel there might be a better (and shorter) way to do this.
The reason I'm doing this is because I need to do stuff with all child_objs.
Worth mentioning:
I use jQuery.each() because this allows looping through objects, while for(), .map() etc. can't handle that properly.
I can't change the structure of the array or its contents
I don't need to use the indexes (args i and j).
Is there a better way?
If you want to ditch jquery (and it's slow speed in .each) and use ES2015+
var myarray = [
{
child_obj: {a:1,b:2,c:3}
},
{
child_obj: {a:4,b:5,c:6},
child_obj2: {a:7,b:8,c:9}
}
];
// specific rewrite of your code would be
myarray.forEach(obj => Object.values(obj.child_obj).forEach(value => {
console.log(value);
}));
console.log('-------');
// other examples
myarray.forEach(obj => Object.values(obj).forEach(value => {
// do things with each "child object"
console.log(value);
}));
myarray.forEach(obj => Object.values(obj).forEach(child => Object.values(child).forEach(value => {
// do things with each property in each child object
console.log(value);
})));
It's not a better way, it's more like alternate.
for (var i = 0; i < myarray.length; i++)
{
var child_obj = myarray[i].child_obj;
// get the keys of this object
var keys = Object.keys(child_obj);
// loop all those keys
for (var keyi = 0; keyi < keys.length; keyi++)
{
var key = keys[keyi];
// get the objects item based on key;
var item = child_obj[key];
}
}
but here you can change their values directly as you are iterating the original vars.
hope that helps
using underscore-js library, you can do the following:
var first = _.map(myarray, element => { return element.child_obj; });
_.each(first, element => {/*do stuff*/});
You could use forEach with a for in loop inside::
myArray.forEach(function(obj){
for(var i in obj){
// do stuff
}
})
Naive recursive approach can be used for primitive types:
function forEachPrimitive(o, f, k) { if (o !== Object(o)) f(k, o)
else for (k in o) forEachPrimitive(o[k], f, k) }
var obj = [ { x: { a: '0', b: true, c: 2 } },
{ y: { d: /3/, e: null, f: undefined } } ]
forEachPrimitive(obj, console.log)

Categories