Dynamically drill down nested array of objects - javascript

How can I dynamically drill down my array of objects? Let me explain. Say I have this array of objects with subarrays:
var arrOfObjects = [
{
name: 'something',
subArray: [ {
name: 'nested something'
} ]
},
{
name: 'something else',
subArray: [ {
name: 'nested something else'
} ]
}];
and a reference to know which array in the hierarchy I need to modify
var referenceArr = [1,0];
How do I use this reference to generate the proper location in my data array, in this case, I would want to get to
arrOfObject[1]['subArray][0]['name'];
// 'subArray' and 'name' are always the same
The reference array could be any length, so
var referenceArr= [0];
indicates modifying:
arrOfObject[0]['name'];

Use this function:
function getValue(source, path){
var result = source;
while(path.length){
result = result[path.shift()];
if(path.length && !result.subArray)
throw new Error('Incorrect path!');
else if(path.length)
result = result.subArray;
else
result = result.name;
}
return result;
}
fiddle

Try this Check this jsfiddle
var arrOfObjects = [
{
name: 'something',
subArray: [ {
name: 'nested something'
} ]
},
{
name: 'something else',
subArray: [ {
name: 'nested something else'
} ]
}];
for(var i=0; i<arrOfObjects.length;i++){
alert(arrOfObjects[i].subArray[0].name)
}

Related

JavaScript / jQuery: Compare 2 jSON objects and output result into new object

I have an api call that replies with an updated jSON object, I also have 1 static jSON object file. I am trying to compare a value in the object per teams with the same name.
So if Team John had 22 in the old file, and has 28 now, the new object should output Team John as 6. Subtracting the 2 and displaying the difference.
I have made a jsFiddle to help understand and update.
LATEST UPDATE: The answer has been solved by mscdeveloper! Check for his post and answer below.
UPDATE (not the answer): I have found a solution while searching in stackoverflow, this does EXACTLY what I want, but I lost the team's name in the process, how can I fix the code to where it doesn't delete it, I know it has something to do with the groupByTypeID function I have?
Updated jsFiddle: https://jsfiddle.net/kqmfsz9n/5/
var obj1 = {
"teams": [
{
name: 'Test 1',
numMembers: '50'
},
{
name: 'Test 2',
numMembers: '12'
}
]
};
var obj2 = {
"teams": [
{
name: 'Test 1',
numMembers: '75'
},
{
name: 'Test 2',
numMembers: '18'
}
]
};
var newObj = {};
function groupByTypeID(arr) {
var groupBy = {};
jQuery.each(arr, function () {
groupBy[this.name] = parseInt(this.numMembers);
});
return groupBy;
}
var userArrayGroups = groupByTypeID(obj2.teams);
var origArrayGroups = groupByTypeID(obj1.teams);
var newObj = [];
for (var prop in userArrayGroups) {
newObj[prop] = userArrayGroups[prop] - origArrayGroups[prop];
newObj.push(userArrayGroups[prop] - origArrayGroups[prop]);
if (newObj[prop] == 0) {
delete newObj[prop];
}
}
console.log(newObj);
All help is appreciated!
Thank you.
var obj1 = {
"teams": [
{
name: 'Test 1',
numMembers: '50'
},
{
name: 'Test 2',
numMembers: '12'
}
]
};
var obj2 = {
"teams": [
{
name: 'Test 1',
numMembers: '75'
},
{
name: 'Test 2',
numMembers: '18'
}
]
};
var newObj = {};
var items_arr=[]; //array of obj2 not exist in obj1
if(obj1.teams){ //if exist array of teams obj1
var o1teams = obj1.teams;
if(obj2.teams){ //if exist array of teams obj2
var o2teams = obj2.teams;
for(var key2 in o2teams){
var o2teams = obj2.teams;
for(var key1 in o1teams){
if(o2teams[key2].name==o1teams[key1].name){
var numMembers_o1_int=parseInt(o1teams[key1].numMembers)||0;
var numMembers_o2_int=parseInt(o2teams[key2].numMembers)||0;
var result_numMembers_int=numMembers_o2_int-numMembers_o1_int;
var result_numMembers=result_numMembers_int+''; //convert to string
var items_for_add=o1teams[key1];
items_for_add.numMembers=result_numMembers;
items_arr.push(items_for_add);
}
}
}
}
}
newObj.items=items_arr;
console.log(newObj);
https://jsfiddle.net/mscdeveloper/uxv1t2a7/3/

Remove $ from JSON Object - possible?

I have an object that looks like this:
{
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
}
Is it possible to remove the $ somehow so the object looks like this:
{
alphabet: {
id: '11',
href: 'abc'
mydata: [[Object]],
status: ['22']
}
}
I'm new to JavaScript and Node JS, and struggling to figure this out. I tried delete object.$; but it does not do anything. I'm pretty sure that I misunderstood this function.
Any help will be appreciated!
Clone $ and use object.assign to merge clone and original object
var obj = {
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [''],
status: ['22']
}
};
var clone = obj.alphabet["$"];
delete obj.alphabet["$"];
Object.assign(obj,clone);
console.log(obj);
You mean put $ object into the root object.
If the key name is always $, you could get the key-value in $ object as below:
let alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
for (let key in alphabet['$']) {
alphabet[key] = alphabet['$'][key]
// maybe you should consider the duplicate key.
}
Here is a function that will loop through the properties of a property in an object and flatten it.
function flattenProp(obj, prop) {
var key;
for(key in obj[prop]) {
obj[key] = obj[prop][key];
}
delete obj[prop];
};
Below is an example of it being used.
var data = {
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
};
console.log(data);
flattenProp(data.alphabet, '$');
console.log(data);
function flattenProp(obj, prop) {
var key;
for(key in obj[prop]) {
obj[key] = obj[prop][key];
}
delete obj[prop];
};
This solution is quite simple -
var obj = {
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
}
var temp = obj.alphabet.$
//copies the internal object to main one
for(var i=0;i<Object.keys(temp).length;i++) {
obj.Object.keys(temp)[0] = temp[Object.keys(temp)[0]];
}
delete obj.alphabet.$ //remove the old object from it
Of course it is possible.
Assuming your data variable (JSON) is named "data":
var data = JSON.parse("your json string");
so data looks like this:
var data = {
alphabet: {
'$': {
id: '11',
href: 'abc'
},
mydata: [[Object]],
status: ['22']
}
}
We just need to iterate over data.alphabet.$, store all its properties to its parent (data.alphabet) and then delete data.alphabet.$:
for(var propname in data.alphabet["$"]) {
var propvalue = data.alphabet["$"][propname];
data.alphabet[propname] = propvalue;
}
delete data.alphabet.$;
here's a snippet:
var data = JSON.parse(`{
"alphabet": {
"$": {
"id": "11",
"href": "abc"
},
"mydata": {},
"status": ["22"]
}
}`)
for(var propname in data.alphabet["$"]) {
var propvalue = data.alphabet["$"][propname];
data.alphabet[propname] = propvalue;
}
delete data.alphabet.$;
document.body.innerHTML = `<pre>${JSON.stringify(data, null, 4)}</pre>`

Javascript Nested Literal to string

I am looking for a technique to run over a object of nested properties and wish to join the properties'.
This is the object I'd like to join:
var array = {
prop1: {
foo: function() {
// Your code here
}
},
prop2: {
bar1: 'some value',
bar2: 'some other value'
}
};
The result should look like this:
[
[ 'prop1', 'foo' ],
[ 'prop2', 'bar1' ],
[ 'prop2', 'bar2' ]
]
Then I'd like to join the array to strings formatted like this:
prop1.foo
prop2.bar1
prop2.bar2
Any tips?
EDIT: Forgot to say it should work for deeper arrays too.
Something along these lines? http://jsfiddle.net/X2X2b/
var array = {
prop1: {
foo: function() {
// Your code here
}
},
prop2: {
bar1: 'some value',
bar2: 'some other value'
}
};
var newA = [],
newB = [];
for ( var obj in array ) {
for (var inObj in array[obj]) {
newA.push([obj, inObj]);
newB.push(obj + '.' + inObj);
}
}
console.log(newA);
console.log(newB);
This is quite a different problem now that you have specified that it needs to support arbitrary depths. In order to solve it we need to use recursion and we need to use a second recursive parameter which keeps track of where we are in the nested hierarchy.
function objectPropertiesToArrays(obj, prepend) {
// result will store the final list of arrays
var result = [];
// test to see if this is a valid object (code defensively)
if(obj != null && obj.constructor === Object) {
for (var propertyName in obj) {
var property = obj[propertyName],
// clone prepend instantiate a new array
list = (prepend || []).slice(0);
// add the property name to the list
list.push(propertyName);
// if it isn't a nested object, we're done
if (property.constructor !== Object) {
result.push(list);
// if it is a nested object, recurse
} else {
// recurse and append the resulting arrays to our list
result = result.concat(objectPropertiesToArrays(property, list));
}
}
}
return result;
}
Example:
var obj = {
prop1: {
foo: function() { }
},
prop2: {
bar1: 'some value',
bar2: 'some other value'
},
prop3: {
x: {
y: [],
z: 'test'
},
erg: 'yar'
}
};
objectPropertiesToArrays(obj);
Returns
[
["prop1", "foo"],
["prop2", "bar1"],
["prop2", "bar2"],
["prop3", "x", "y"],
["prop3", "x", "z"],
["prop3", "erg"]
]

Sort array of objects by arbitrary list in JavaScript

Given an array of objects like this:
objects = [
{ id: 'aaaa', description: 'foo' },
{ id: 'bbbb', description: 'bar' },
{ id: 'cccc', description: 'baz' }
];
And an array of strings like this:
order = [ 'bbbb', 'aaaa', 'cccc' ];
How would I sort the first array so that the id attribute matches the order of the second array?
Try this:
objects.sort(function(a, b){
return order.indexOf(a.id) - order.indexOf(b.id)
});
Assuming the variables are like you declared them in the question, this should return:
[
{ id: 'bbbb', description: 'bar' },
{ id: 'aaaa', description: 'foo' },
{ id: 'cccc', description: 'baz' }
];
(It actually modifies the objects variable)
You need a way to translate the string into the position in the array, i.e. an index-of function for an array.
There is one in newer browsers, but to be backwards compatible you need to add it if it's not there:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(str) {
var i;
for (i = 0; i < this.length; i++) if (this[i] == str) return i;
return -1;
}
}
Now you can sort the array by turning the string into an index:
objects.sort(function(x,y){ return order.indexOf(x.id) - order.indexOf(y.id); });
Demo: http://jsfiddle.net/Guffa/u3CQW/
Use a mapping object for (almost) constant access time:
/* Create a mapping object `orderIndex`:
{
"bbbb": 0,
"aaaa": 1,
"cccc": 2
}
*/
const orderIndex = {}
order.forEach((value, index) => orderIndex[value] = index);
// Sort
objects.sort((a, b) => orderIndex[a.id] - orderIndex[b.id]);
// data
const objects = [
{ id: 'aaaa', description: 'foo' },
{ id: 'bbbb', description: 'bar' },
{ id: 'cccc', description: 'baz' }
];
const order = [ 'bbbb', 'aaaa', 'cccc' ];
/* Create a mapping object `orderIndex`:
{
"bbbb": 0,
"aaaa": 1,
"cccc": 2
}
*/
const orderIndex = {}
order.forEach((value, index) => orderIndex[value] = index);
// Sort
objects.sort((a, b) => orderIndex[a.id] - orderIndex[b.id]);
// Log
console.log('orderIndex:', orderIndex);
console.log('objects:', objects);

Javascript: How convert array of objects to object with sorted unique arrays?

Have data that has this kind of structure:
$input = [ { animal: 'cat', name: 'Rocky', value: 1 },
{ animal: 'cat', name: 'Spot', value: 2 },
{ animal: 'dog', name: 'Spot', value: 3 } ];
Need fastest possible method for converting to this format:
$output = { animal: [ 'cat', 'dog' ],
name: [ 'Rocky', 'Spot' ],
value: [ 1, 2, 3 ] };
The output should have keys equal to each of the keys in each object from the input. And the output values should be arrays with the sorted unique values. I found a few ways to do it using nested loops, but slower than I would like. With 30,000 elements to the input array with 8 keys for each of the objects, the best I have been able to do is 300ms in Chrome. Would like to get down to 100ms. Is there any faster method using a map or reduce?
Yet another way for modern browsers:
$input.reduce(function(acc, obj) {
Object.keys(obj).forEach(function(k) {
acc[k] = (acc[k] || []).concat(obj[k])
})
return acc
},{})
Here's one way.
$input = [ { animal: 'cat', name: 'Rocky', value: 1 },
{ animal: 'cat', name: 'Spot', value: 2 },
{ animal: 'dog', name: 'Spot', value: 3 } ];
$output = {animal:{},name:{},value:{}};
$input.forEach(function(v,i) {
$output.animal[v.animal] = 1;
$output.name[v.name] = 1;
$output.value[v.value] = 1;
});
$output.animal = Object.keys($output.animal);
$output.name = Object.keys($output.name);
$output.value = Object.keys($output.value);
It prevents having to test each Array every time. You can performance compare to see if it helps.
live example: http://jsfiddle.net/TJVtj/1/
If you don't want to hardcode the keys, you can make the solution generic.
var keys = Object.keys($input[0]),
$output = {};
keys.forEach(function(v) {
$output[v] = {};
});
$input.forEach(function(v) {
keys.forEach(function(vv) {
$output[vv][v[vv]] = 1;
});
});
keys.forEach(function(v) {
$output[v] = Object.keys($output[v]);
});
live example: http://jsfiddle.net/TJVtj/2/
Warning. All the values will be strings since they're fetched as object keys.
function inArray(needle, haystack) {
var length = haystack.length;
for(var i = 0; i < length; i++) {
if(haystack[i] == needle) return true;
}
return false;
}
Above function is used to check duplicates
$output={};
for(i=0; i< $input.length; i++)
{
if(!$output.animal) $output.animal=[];
if(!$output.name) $output.name=[];
if(!$output.value) $output.value=[];
var ani=$input[i];
if(ani.animal && !inArray(ani.animal, $output.animal)) $output.animal.push(ani.animal);
if(ani.name && !inArray(ani.name, $output.name)) $output.name.push(ani.name);
if(ani.value) $output.value.push(ani.value);
}
DEMO.
// If you don't know the objects all have the same keys you need to look at each one-
var output= {},
input= [{
animal:'cat', name:'Rocky', value:1
},{
animal:'cat', name:'Spot', value:2
},{
animal:'dog', name:'Spot', value:3
}];
input.forEach(function(itm){
for(var p in itm){
if(itm.hasOwnProperty(p)){
if(!output[p]) output[p]= [];
if(output[p].indexOf(itm[p])== -1) output[p].push(itm[p]);
}
}
});
Run.expose(output)// nonstandard object to string method
// returned value: (String)
{
animal:[
'cat',
'dog'
],
name:[
'Rocky',
'Spot'
],
value:[
1,
2,
3
]
}
Try Underscore, it's magnificent with this kind of tasks)

Categories

Resources