Traversal of an object is easy, but I found it hard to figure out the traversal paths for myself.
For example, here we have data like below:
data = {
a: 'A',
b: {
d: [
'F',
'G'
],
e: 'D'
},
c: 'C'
}
I want to output the traversal paths like this:
['a']
['b', 'd', 0]
['b', 'd', 1]
['b', 'e']
['c']
How do I write the algorithm?
function rec(currentObject, path) {
if (typeof currentObject !== "string" && currentObject.length) {
for (var i = 0; i < currentObject.length; i += 1) {
rec(currentObject[i], path.concat(i));
}
} else if (typeof currentObject === "object") {
for (var item in currentObject) {
rec(currentObject[item], path.concat(item))
}
} else {
console.log(path);
}
}
rec(data, []);
Output
[ 'a' ]
[ 'b', 'd', 0 ]
[ 'b', 'd', 1 ]
[ 'b', 'e' ]
[ 'c' ]
Related
Is there a simple way in javascript to take a flat array and convert into an object with the even-indexed members of the array as properties and odd-indexed members as corresponding values (analgous to ruby's Hash[*array])?
For example, if I have this:
[ 'a', 'b', 'c', 'd', 'e', 'f' ]
Then I want this:
{ 'a': 'b', 'c': 'd', 'e': 'f' }
The best I've come up with so far seems more verbose than it has to be:
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = {};
for (var i = 0, len = arr.length; i < len; i += 2) {
obj[arr[i]] = arr[i + 1];
}
// obj => { 'a': 'b', 'c': 'd', 'e': 'f' }
Is there a better, less verbose, or more elegant way to do this? (Or I have just been programming in ruby too much lately?)
I'm looking for an answer in vanilla javascript, but would also be interested if there is a better way to do this if using undercore.js or jQuery. Performance is not really a concern.
Pretty sure this will work and is shorter:
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = {};
while (arr.length) {
obj[arr.shift()] = arr.shift();
}
See shift().
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = arr.reduce( function( ret, value, i, values ) {
if( i % 2 === 0 ) ret[ value ] = values[ i + 1 ];
return ret;
}, { } );
If you need it multiple times you can also add a method to the Array.prototype:
Array.prototype.to_object = function () {
var obj = {};
for(var i = 0; i < this.length; i += 2) {
obj[this[i]] = this[i + 1];
}
return obj
};
var a = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
a.to_object(); // => { 'a': 'b', 'c': 'd', 'e': 'f' }
You could first chunk your array into groups of two:
[['a', 'b'], ['c', 'd'], ['e', 'f']]
so that is is in a valid format to be used by Object.fromEntries(), which will build your object for you:
const chunk = (arr, size) => arr.length ? [arr.slice(0, size), ...chunk(arr.slice(size), size)] : [];
const arr = ['a', 'b', 'c', 'd', 'e', 'f'];
const res = Object.fromEntries(chunk(arr, 2));
console.log(res); // {a: "b", c: "d", e: "f"}
With underscore.js and lodash, you don't need to implement the chunk() method yourself, and can instead use _.chunk(), a method built into both libraries. The full lodash equivalent of the above would be:
// lodash
> _.fromPairs(_.chunk(arr, 2));
> {a: "b", c: "d", e: "f"}
Using _.fromPairs provides better browser support, so if using lodash, it is preferred over Object.fromEntries()
Similarly, we can use _.object() if you're using underscore.js to build the object:
// underscore.js
> _.object(_.chunk(arr, 2));
> {a: "b", c: "d", e: "f"}
Although it is a common problem but I couldn't find any lead to get the desired result. So here is the problem. I have the following array:
[
[ 'a' ]
[ 'a', 'b' ]
[ 'a', 'c' ]
[ 'a', 'c', 'd' ]
[ 'a', 'c', 'd', 'e' ]
]
And what I want as an end result is an object like this:
{
a: {
b: {},
c: { d: { e: {} } }
}
}
I don't understand which approach would be better to get this result and how to achieve it.
You need a double reduce, one for the outer array and one for the keys and the nesting objects.
var data = [['a'], ['a', 'b'], ['a', 'c'], ['a', 'c', 'd'], ['a', 'c', 'd', 'e']],
result = data.reduce((r, keys) => {
keys.reduce((o, k) => o[k] = o[k] || {}, r);
return r;
}, {});
console.log(result);
I have list of array associated with object. The requirement is to make a new key that will have all key value in there.
var obj = {
all:[
obj.one,
obj.two
],
one:[
'a',
'b',
'c'
],
two:[
'd',
'e',
'f',
'g'
]
}
//Wanted result
var obj = {
all:[
'a',
'b',
'c'
'd',
'e',
'f',
'g'
],
one:[
'a',
'b',
'c'
],
two:[
'd',
'e',
'f',
'g'
]
}
function accumulateKeyValues(obj){
var accumulated = [];
for(var key in obj)
accumulated = accumulated.concat(obj[key]);
obj["all"] = accumulated;
}
EXAMPLE:
function accumulateKeyValues(obj){
var accumulated = [];
for(var key in obj)
accumulated = accumulated.concat(obj[key]);
obj["all"] = accumulated;
}
var obj = {
one:[
'a',
'b',
'c'
],
two:[
'd',
'e',
'f',
'g'
]
};
accumulateKeyValues(obj);
console.log(obj);
You could get all keys of the object and take all values for a new array.
var obj = { one:['a', 'b', 'c'], two: ['d', 'e', 'f', 'g'] };
obj.all = Object.keys(obj).reduce(function (r, k) {
return r.concat(obj[k]);
}, []);
console.log(obj);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I need help converting several arrays:
x = ['a', 'b', 'c']
y = ['d', 'e', 'f']
z = ['d', 'g', 'h']
Into a single JSON:
{
a: { b: { c: 'done' }},
d: { e: { f: 'done' },
g: { h: 'done' }}
}
Is this possible using recursion? I can't seem to get it working properly so I was wondering if there is already an easy way to do this in JS.
var struct = {};
var paths = [
['a', 'b', 'c'],
['d', 'e', 'f'],
['d', 'g', 'h']
];
paths.forEach(function (path) {
var ref;
ref = struct;
path.forEach(function (elem, index) {
if (!ref[elem]) {
ref[elem] = index === path.length - 1 ? "done": {};
}
ref = ref[elem];
});
});
console.log(JSON.stringify(struct, null, "\t"));
Output:
{
"a": {
"b": {
"c": "done"
}
},
"d": {
"e": {
"f": "done"
},
"g": {
"h": "done"
}
}
}
Note: this script will fail if your input is like:
var paths = [
['a', 'b', 'c'],
['a', 'b', 'c', 'd' ]
];
It decided c should be "done" but then there is another level. maybe this wont ever happen, if it does, figure out what you want the result to be.
A version with Array#forEach() and Array#reduce()
var x = ['a', 'b', 'c'],
y = ['d', 'e', 'f'],
z = ['d', 'g', 'h'],
object = function (array) {
var o = {};
array.forEach(function (a) {
var last = a.pop();
a.reduce(function (r, b) {
r[b] = r[b] || {};
return r[b];
}, o)[last] = 'done';
});
return o;
}([x, y, z]);
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');
Is there a simple way in javascript to take a flat array and convert into an object with the even-indexed members of the array as properties and odd-indexed members as corresponding values (analgous to ruby's Hash[*array])?
For example, if I have this:
[ 'a', 'b', 'c', 'd', 'e', 'f' ]
Then I want this:
{ 'a': 'b', 'c': 'd', 'e': 'f' }
The best I've come up with so far seems more verbose than it has to be:
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = {};
for (var i = 0, len = arr.length; i < len; i += 2) {
obj[arr[i]] = arr[i + 1];
}
// obj => { 'a': 'b', 'c': 'd', 'e': 'f' }
Is there a better, less verbose, or more elegant way to do this? (Or I have just been programming in ruby too much lately?)
I'm looking for an answer in vanilla javascript, but would also be interested if there is a better way to do this if using undercore.js or jQuery. Performance is not really a concern.
Pretty sure this will work and is shorter:
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = {};
while (arr.length) {
obj[arr.shift()] = arr.shift();
}
See shift().
var arr = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
var obj = arr.reduce( function( ret, value, i, values ) {
if( i % 2 === 0 ) ret[ value ] = values[ i + 1 ];
return ret;
}, { } );
If you need it multiple times you can also add a method to the Array.prototype:
Array.prototype.to_object = function () {
var obj = {};
for(var i = 0; i < this.length; i += 2) {
obj[this[i]] = this[i + 1];
}
return obj
};
var a = [ 'a', 'b', 'c', 'd', 'e', 'f' ];
a.to_object(); // => { 'a': 'b', 'c': 'd', 'e': 'f' }
You could first chunk your array into groups of two:
[['a', 'b'], ['c', 'd'], ['e', 'f']]
so that is is in a valid format to be used by Object.fromEntries(), which will build your object for you:
const chunk = (arr, size) => arr.length ? [arr.slice(0, size), ...chunk(arr.slice(size), size)] : [];
const arr = ['a', 'b', 'c', 'd', 'e', 'f'];
const res = Object.fromEntries(chunk(arr, 2));
console.log(res); // {a: "b", c: "d", e: "f"}
With underscore.js and lodash, you don't need to implement the chunk() method yourself, and can instead use _.chunk(), a method built into both libraries. The full lodash equivalent of the above would be:
// lodash
> _.fromPairs(_.chunk(arr, 2));
> {a: "b", c: "d", e: "f"}
Using _.fromPairs provides better browser support, so if using lodash, it is preferred over Object.fromEntries()
Similarly, we can use _.object() if you're using underscore.js to build the object:
// underscore.js
> _.object(_.chunk(arr, 2));
> {a: "b", c: "d", e: "f"}