Given the following array of json objects:
var items = [
{id:1, parentId:0, name:'item1'},
{id:2, parentId:1, name:'item1.2'},
{id:3, parentId:1, name:'item1.3'},
{id:4, parentId:3, name:'item3.4'},
{id:5, parentId:3, name:'item3.5'},
...more nesting, levels, etc.
];
And a base object like:
var myObj = function(id, parentId, name, children){
this.id = id;
this.parentId = parentId;
this.name = name;
this.children = children;
};
how do I use recursion to loop through this items array and build a new array like so:
var newArray = [
new myObj(1, 0, 'item1', [
new myObj(2, 1, 'item1.2', []),
new myObj(3, 1, 'item1.3', [
new myObj(4, 3, 'item3.4', []),
new myObj(5, 3, 'item3.5', [])
])
]);
];
any help is greatly appreciated
edit:
the parent/child relationship can be infinite. so i'm looking for a recursion function that would convert the first "items" array into the second "newarray"
The title of your question is a bit misleading. You're trying to convert an array of items into a tree-like nested object.
Your use of the Object constructor is a bit redundant. Use quasi-literal notation ({foo:bar}) instead. Actually, you don't even need to create new objects, you can use the original ones.
First, convert the list to an object to facilitate referencing by id:
var map = {}
for (var i = 0; i < items.length; i++) {
map[items[i].id] = items[i];
}
Now, iterate through the items and add children array:
var newArray = [];
for (id in map) {
var item = map[id];
var parent = map[item.parentId];
if (parent) {
parent.children = parent.children || [];
parent.children.push(item); // add reference to item
} else { // root
newArray.push(item);
}
}
Note that this modifies the original items array, and newArray holds pointers to its entries. If you don't want that, create a copy of items first.
I don't know if this helps, but in this fiddle there's an iterative solution that creates that newArray. Using a json obj as an array and then adding the children as you iterate over the items array.
Related
I have an object. I would like to be able to dynamically create an array, then create another object that contains the key-value pairs that correspond with properties from the array that I created.
For example, if I have the following object...
var churchMembers = {
John: 'fsiolfjdklsjds#yahoo.com',
Betty: 'fowifj#hotmail.com',
Christopher: 'fsis#yahoo.com',
James: 'wfowji#gmail.com',
Deep: 'abab#msn.com'
};
and I create the following array:
var peopleComing = ['John', 'Christopher', 'James'];
I want the following response
var peopleList = {
John: 'fsiolfjdklsjds#yahoo.com',
Christopher: 'fsis#yahoo.com',
James: 'wfowji#gmail.com'
};
Right now I'm trying to use a for loop and all I'm doing is iterating through the object properties, which is not giving me anything. Going with the Object.keys route seems counterproductive, although that would easily allow me to filter out the correct names. Thanks. SIAP
You can use Array#forEach to iterate over your list of names, and get the email for each name and add it to your peopleList.
var peopleList = {};
peopleComing.forEach(function(name){
peopleList[name] = churchMembers[name];
});
Ignoring the typo you have in your code, the below code should be capable of initializing peopleList with what you want.
var churchMembers = {
John: "fsiolfjdklsjds#yahoo.com"
Betty: "fowifj#hotmail.com",
Christopher: "fsis#yahoo.com",
James: "wfowji#gmail.com",
Deep: "abab#msn.com"
},
peopleComing = ["John", "Christopher", "James"],
peopleList = {};
for (var i = 0, j = peopleComing.length; i < j; i++) {
peopleList[peopleComing[i]] = churchMembers[peopleComing[i]];
}
I know it's simple, but I don't get it.
I have this code:
// My object
const nieto = {
label: "Title",
value: "Ramones"
}
let nietos = [];
nietos.push(nieto.label);
nietos.push(nieto.value);
If I do this I'll get a simple array:
["Title", "Ramones"]
I need to create the following:
[{"01":"Title", "02": "Ramones"}]
How can I use push() to add the object into the nietos array?
You have to create an object. Assign the values to the object. Then push it into the array:
var nietos = [];
var obj = {};
obj["01"] = nieto.label;
obj["02"] = nieto.value;
nietos.push(obj);
Create an array of object like this:
var nietos = [];
nietos.push({"01": nieto.label, "02": nieto.value});
return nietos;
First you create the object inside of the push method and then return the newly created array.
can be done like this too.
// our object array
let data_array = [];
// our object
let my_object = {};
// load data into object
my_object.name = "stack";
my_object.age = 20;
my_object.hair_color = "red";
my_object.eye_color = "green";
// push the object to Array
data_array.push(my_object);
Using destructuring assignment (ES6)
const nieto = {label: 'title', value: 'ramones' }
const modifiedObj = {01: nieto.label, 02: nieto.value}
let array = [
{03: 'asd', 04: 'asd'},
{05: 'asd', 06: 'asd'}
]
// push the modified object to the first index of the array
array = [modifiedObj, ...array]
console.log(array)
If you'd like to push the modified object to the last index of the array just change the destructured array ...array to the front.
array = [...array, modifiedObj]
Well, ["Title", "Ramones"] is an array of strings. But [{"01":"Title", "02", "Ramones"}] is an array of object.
If you are willing to push properties or value into one object, you need to access that object and then push data into that.
Example:
nietos[indexNumber].yourProperty=yourValue; in real application:
nietos[0].02 = "Ramones";
If your array of object is already empty, make sure it has at least one object, or that object in which you are going to push data to.
Let's say, our array is myArray[], so this is now empty array, the JS engine does not know what type of data does it have, not string, not object, not number nothing. So, we are going to push an object (maybe empty object) into that array. myArray.push({}), or myArray.push({""}).
This will push an empty object into myArray which will have an index number 0, so your exact object is now myArray[0]
Then push property and value into that like this:
myArray[0].property = value;
//in your case:
myArray[0]["01"] = "value";
I'm not really sure, but you can try some like this:
var pack = function( arr ) {
var length = arr.length,
result = {},
i;
for ( i = 0; i < length; i++ ) {
result[ ( i < 10 ? '0' : '' ) + ( i + 1 ) ] = arr[ i ];
}
return result;
};
pack( [ 'one', 'two', 'three' ] ); //{01: "one", 02: "two", 03: "three"}
The below solution is more straight-forward. All you have to do is define one simple function that can "CREATE" the object from the two given items. Then simply apply this function to TWO arrays having elements for which you want to create object and save in resultArray.
var arr1 = ['01','02','03'];
var arr2 = ['item-1','item-2','item-3'];
resultArray = [];
for (var j=0; j<arr1.length; j++) {
resultArray[j] = new makeArray(arr1[j], arr2[j]);
}
function makeArray(first,second) {
this.first = first;
this.second = second;
}
This solution can be used when you have more than 2 properties in any object.
const nieto = {
label: "Title",
value: "Ramones"
}
let nietos = [];
let xyz = Object.entries(nieto)
xyz.forEach((i,j)=>{
i[0] = `${(j+1).toLocaleString("en-US", {
minimumIntegerDigits: 2,
useGrouping: false,
})}`
})
nietos.push(Object.fromEntries(xyz))
I have two arrays and I want to join them
function test()
{
var arr1 = [
{"id":1,"name":"Michale Sharma","gender":"Male","age":25,"salary":10000},
{"id":2,"name":"Sunil Das","gender":"Male","age":24,"salary":5000},{"id":3,"name":"Robin Pandey","gender":"Male","age":35,"salary":45000},{"id":4,"name":"Mona Singh","gender":"Female","age":27,"salary":12000}
];
var arr2 = [
{"Deptid":4,"Deptname":"IT"},
{"Deptid":1,"Deptname":"HR"},
{"Deptid":3,"Deptname":"HW"},
{"Deptid":24,"Deptname":"HW4"}
];
var res = Pack(arr1,arr2);
console.log(res);
}
function Pack()
{
var args = [].slice.call(arguments);
args.join(',');
return args;
}
I am expecting the output as
[{"Employees":[{"id":1,"name":"Michale Sharma","gender":"Male","age":25,"salary":10000},{"id":2,"name":"Sunil Das","gender":"Male","age":24,"salary":5000},{"id":3,"name":"Robin Pandey","gender":"Male","age":35,"salary":45000},{"id":4,"name":"Mona Singh","gender":"Female","age":27,"salary":12000}],"Departments":[{"Deptid":1,"Deptname":"IT"},{"Deptid":2,"Deptname":"HR"},{"Deptid":3,"Deptname":"HW"},{"Deptid":4,"Deptname":"SW"}]}]
But not able to. How to do it?
I have already tried with Concat() function of Javascript but it didn't helped.
N.B.~ As it can be assumed that there can be variable number of arrays in the Pack function.
Couldn't you do something like:
var newArray = [ { "Employees": arr1, "Departments": arr2 } ]
Try this:
var arr1 = [
{"id":1,"name":"Michale Sharma","gender":"Male","age":25,"salary":10000},
{"id":2,"name":"Sunil Das","gender":"Male","age":24,"salary":5000},{"id":3,"name":"Robin Pandey","gender":"Male","age":35,"salary":45000},{"id":4,"name":"Mona Singh","gender":"Female","age":27,"salary":12000}
];
var arr2 = [
{"Deptid":4,"Deptname":"IT"},
{"Deptid":1,"Deptname":"HR"},
{"Deptid":3,"Deptname":"HW"},
{"Deptid":24,"Deptname":"HW4"}
];
var json = {};
var jsonArr = [];
json.Employees = arr1;
json.Department = arr2;
jsonArr.push(json);
document.write(JSON.stringify(jsonArr));
From the expected JSON, what you need is neither "merging", nor "concatenation". You want to put an array inside an object.
What you want is below:
var output = [{
"Employees": arr1,
"Department": arr2
}];
Note that output is an array according to your expectation. Why you need an array is something I dont understand.
Ok, so i put a little fiddle together for you, Here
Most of your code stays the same, except I added this to your test function:
var myObjToMerge = [{Employees:[]},{Departments:[]}];
var res = Pack(myObjToMerge,arr1,arr2);
You need to give 'Pack' some object to merge the arrays to, so I created an arbritary array of objects modeled after your example. Note that this array of objects can come from anywhere and this method doesn't require it to be known ahead of time like some of the other examples.
Then I changed the 'Pack' function:
function Pack()
{
var objToMerge = arguments[0];
for(var i = 0;i<objToMerge.length;i++)
{
if(arguments.length > i+1)
{
var firstProperty = Object.keys(objToMerge[i])[0];
objToMerge[i][firstProperty]= arguments[i+1];
}
}
return objToMerge;
}
The idea here is that 'Pack' grabs the first argument, your object to merge the remaining arguments into. I would suggest using function parameters, but that is your call.
Then, I iterate through the objects in the objToMerge array (there are two objects: Employees and Departments).
I assume that the remaining items in arguments is in the correct order and I grab the next item in arguments and assign to to the first property in the object I am currently looped in.
The line:
var firstProperty = Object.keys(objToMerge[i])[0];
Will return the string value of the first property in an object. We then use this to set the next array in arguments to that property:
objToMerge[i][firstProperty]= arguments[i+1];
there are a great deal of assumptions here and ways to improve, but you can see that it works in the fiddle and you can improve upon it as needed.
function test() {
var arr1 = {"Employees" : [
{"id":1,"name":"Michale Sharma","gender":"Male","age":25,"salary":10000},
{"id":2,"name":"Sunil Das","gender":"Male","age":24,"salary":5000},{"id":3,"name":"Robin Pandey","gender":"Male","age":35,"salary":45000},{"id":4,"name":"Mona Singh","gender":"Female","age":27,"salary":12000}
]};
var arr2 = {"Departments":[
{"Deptid":4,"Deptname":"IT"},
{"Deptid":1,"Deptname":"HR"},
{"Deptid":3,"Deptname":"HW"},
{"Deptid":24,"Deptname":"HW4"}
]};
var res = Pack(arr1,arr2);
console.log(res);
}
function Pack()
{
var results = [];
arguments.forEach(function(element){
results.push(element);
});
return results;
}
I have an array of objects as
var obj = {'name': 'John'};
var obj2 = {'name': 'Sam'};
var arr = [];
arr.push(obj);
arr.push(obj2);
Now I create a new array arr2 as
arr2 = arr.slice();
Now if I change arr2[0]['name'] = 'David';
then arr1[0]['name'] also becomes 'David';
How can we prevent any object value of arr from changing when arr2 object values are changed.
You’ll have to clone each object, not just the array:
function cloneObject(obj) {
var result = {};
for (var k in obj) {
if (Object.prototype.hasOwnProperty.call(obj, k)) {
result[k] = obj[k];
}
}
return result;
}
var arr2 = arr.map(cloneObject);
Is there a way we can prevent the objects from changing?
Yes, there’s Object.freeze:
arr.forEach(Object.freeze);
When you copy the array you are only copying the values in the array, but the values are references to objects. You end up with two separate arrays, but with references to the same objects.
You would need to make a deep copy, i.e. copy everything at every level:
var arr2 = JSON.parse(JSON.stringify(arr));
Now you have a completely separate copy of the array and everything in it.
I want sort values by array Another
for example
var objName = [{id:1, name:"one"},{id:2, name:"two"}, {id:3, name:"three"}];
var sortById = [1,3,2];
I want this output in that order
1 one
3 three
2 two
Stuff objName elements into a hash (i.e. object) indexed by id, then map the sortById array onto the hash values.
Exact code left as an exercise for the reader.
sorted=new Array()
for(var id_index=0;id_index<sortById.length;id_index++)
{
for(var obj_index=0;obj_index<objName.length;obj_index++){
if (objName[obj_index].id===sortById[id_index]) sorted.push(objName[obj_index])
}
}
//now sorted is the new sorted array. if you want to overwrite the original object:
objName=sorted;
Supposing that the length of both arrays are the same you can first create a hash:
var objName = [{id:1, name:"one"},{id:2, name:"two"}, {id:3, name:"three"}];
var myHash = {};
for(var i = 0; i<objName.length;i++){
myHash[objName[i].id] = objName[i];
}
Once you have this hash, you can loop over your keys array and get the values out:
var sortById = [1,3,2];
var sortedArray = [];
for(var i = 0; i<sortById.length;i++){
sortedArray.push(myHash[sortById[i]]);
}
Something clear and readable (subjective, probably not for everyone):
var result = [];
sortById.forEach(function(id) {
result = result.concat(objName.filter(function(i) {
return i.id == id;
}));
});
JSFiddle: http://jsfiddle.net/RLH6F/
Implemented just for fun.
Warning: O(n^2)
PS: I agree it would be better just give the recipe without the code, but as soon as there are already community members provided the copy-paste solutionы I decided to provide at least a nice looking one.