Convert a nested array in to a nested object in javascript - javascript

I want to write a code in javascript to convert a nested array in to a nested object. The point is every single elements in the nested array would be an array itself, so should convert to a nested object:
Examples:
[['a', 1], ['b', 2], ['c', [['d', 4]]]] => { a: 1, b: 2, c: { d: 4 } }
[['a', 1], ['b', 2], ['c', [['d', [['e', 5], ['f', 6]]]]]]
=> { a: 1, b: 2, c: { d: { e: 5, f: 6 } } }
I tried to go with this concept:
define a function to iterate over the base array. for every single element, it will make a key:value for the object. if the value is an array, the function will call itself.
but Actually I dont know how to write it.
const nestedArrayToObject = function (arr) {
let obj = {};
for (let i = 0; i < arr.length; i++) {
let key = arr[i][0];
let val = arr[i][1];
if (!Array.isArray(val)) {
obj[key] = val;
} else {
nestedArrayToObject(val); ???
}
}
return obj;
};

You can use Object.fromEntries to convert an array of key-value pairs to an object. For each value that is also an array, recursively call the conversion function.
function convert(arr) {
return Object.fromEntries(arr.map(([k, v]) =>
[k, Array.isArray(v) ? convert(v) : v]));
}
console.log(convert([['a', 1], ['b', 2], ['c', [['d', 4]]]]));
console.log(convert([['a', 1], ['b', 2], ['c', [['d', [['e', 5], ['f', 6]]]]]]));

Related

Reduce multidimensional with string and numbers array in Javascript

I have some idea of how reduce works, but I'm having problem with a multidimensional array. How can I reduce this:
y = [['x', 0.5], ['x', 0.5], ['z', 2], ['z', 2]];
into this:
y = [['x', 1], ['z', 4]];
Thanks!
You could reduce with an accumulated object that store sum of key, then use Object.entries() to transform it back to an array of array
const y = [
["x", 0.5],
["x", 0.5],
["z", 2],
["z", 2],
]
const res = Object.entries(
y.reduce((acc, [key, value]) => {
acc[key] = (acc[key] || 0) + value
return acc
}, {})
)
console.log(res)

JavaScript How to replace first element of an array with each element of another array

I have two arrays and I need to replace the first element of the first array with each elements of the second array:
let firstArray = [
[1, 'a', 'hello'],
[2, 'b', 'world'],
[3, 'c', 'other'],
...
];
let secondArray = [1, 3, 7, ...];
// Result:
// [
// [1, 'a', 'hello'],
// [3, 'b', 'world'],
// [7, 'c', 'other'],
// ...
// ]
I tried doing something like this:
firstArray.map(f => {
secondArray.forEach(s => {
f.splice(0, 1, s);
})
})
But this replace the first element only with the last element of second array
Use .map to transform an array into another:
const firstArray = [
[1, 'a', 'hello'],
[2, 'b', 'world'],
[3, 'c', 'other'],
];
const secondArray = [1, 3, 7];
const transformed = firstArray.map(([, ...rest], i) => [secondArray[i], ...rest]);
console.log(transformed);
Another option:
const firstArray = [
[1, 'a', 'hello'],
[2, 'b', 'world'],
[3, 'c', 'other'],
];
const secondArray = [1, 3, 7];
const transformed = firstArray.map((item, i) => [secondArray[i]].concat(item.slice(1)));
console.log(transformed);
You could assign the array to a new array and take the new value to a specified index.
const
firstArray = [[1, 'a', 'hello'], [2, 'b', 'world'], [3, 'c', 'other']],
secondArray = [1, 3, 7],
result = firstArray.map((a, i) => Object.assign([], a, { 0: secondArray[i] }));
console.log(result);

Compare two arrays containing objects including other objects, arrays, etc

Look at these examples of array comparative code:
// example-1
let array1 = ['a', 'b'];
let array2 = ['a', 'b'];
console.log(array1.equals(array2)); // returns true
// example-2
let array1 = ['a', 'b', 1];
let array2 = ['a', 'b', 1];
console.log(array1.equals(array2)); // returns true
// example-3
let array1 = ['a', 'b', {'a': 1, 'b': 2}];
let array2 = ['a', 'b', {'b': 2, 'a', 1}];
console.log(array1.equals(array2)); // returns false
I'm looking for a way to compare the arrays containing objects in them, but irrespective of the order of elements in a nested object, like mentioned in the example-3 above.
You should JSON.stringify() the arrays and compare them like so:
var arr1 = ['a', 'b', {'a': 1}];
var arr2 = ['a', 'b', {'a': 1}];
console.log(JSON.stringify(array1) == JSON.stringify(array2));
This works because it converts arrays of objects into a much simpler comparative state (JSON strings). This will only work if the arrays contain their properties in the same ordered in the OP's example.
underscore way:
_.isEqual(array1, array2)
You can use JSON.stringify() to get the JSON string and compare them with ===:
let array1 = ['a', 'b', {'a': 1}];
let array2 = ['a', 'b', {'a': 1}];
console.log(JSON.stringify(array1) === JSON.stringify(array2)); // returns true
You can just write a function the will recursively check until it gets down to primitives. For example:
function deepEqual(o1, o2){
if (Array.isArray(o1)) {
return Array.isArray(o2)
&& o1.length === o2.length
&& o1.every((item, idx) => deepEqual(item, o2[idx]))
}
if (typeof(o1) == 'object' && o1 != null){ // (typeof null == 'object)
return typeof(o2) == 'object'
&& o2 != null
&& deepEqual(Object.entries(o1)
.sort((a,b) => a[0].localeCompare(b[0])),Object.entries(o2).sort((a,b) => a[0].localeCompare(b[0])))
}
return o1 === o2
}
//Object order doesn't matter
let ob1 = [1, 2, {a: "test", b:"hello"}, 4]
let ob2 = [1, 2, {b:"hello", a: "test", }, 4]
console.log(deepEqual(ob1, ob2))
ob1 = [1, 2, {a: "test", b:"hello"}, 4]
ob2 = [1, 2, {b:"hello", a: "non-test", }, 4]
console.log(deepEqual(ob1, ob2))
// array order matters:
ob1 = [2, 1, {a: "test", b:"hello"}, 4]
ob2 = [1, 2, {b:"hello", a: "test", }, 4]
console.log(deepEqual(ob1, ob2))
console.log(deepEqual("test", "test"))
console.log(deepEqual(null, {a:"test"}))
// etc.

How to pivot a javascript array

I have this javascript array:
[['a', 'x', 1],
['a', 'y', 2],
['b', 'x', 3],
['b', 'z', 4],
['c', 'y', 5],
['c', 'z', 6]]
How do I pivot it to something like below with the 2nd column ('x', 'y', 'z') from above going across.
[['a', 1, 2, null],
['b', 3, null, 4],
['c', null, 5, 6]]
EDIT:
Sorry I was unclear. The answers so far seem to be referencing a static length/value for x, y, z. The array will be dynamic and can have anything in the 2nd column (ex. 't','u','v','w' instead of 'x','y','z'). I think I need to fill the array up first with nulls for all the possible combinations and then push in the values.
Thanks..
Going by Fabricio's comment, here is how you can accomplish something similar:
var result = {};
for(var i=0;i< basearray.length;i++){
if(!result[basearray[i][0]]){
result[basearray[i][0]]={};
}
result[basearray[i][0]][basearray[i][1]]=basearray[i][2];
}
Note that this returns an object or hashmap, not strictly an array, but the data is more organised and it can easily be turned into an array if you so wish. Here is a demonstration (check your console).
By adding this code:
var count=0;
for(var key in result){
result[count]=[];
result[count][0]=key;
result[count][1]=result[key].x||null;
result[count][2]=result[key].y||null;
result[count][3]=result[key].z||null;
count++;
}
your result object now simulates both structures, your original array of arrays, and the suggested key value pairs. You can see the results here: http://jsfiddle.net/9Lakw/3/
Here is what result looks like:
{
"a":{
"x":1,
"y":2
},
"b":{
"x":3,
"z":4
},
"c":{
"y":5,
"z":6
},
"0":[
"a",
1,
2,
null
],
"1":[
"b",
3,
null,
4
],
"2":[
"c",
null,
5,
6
]
}
Here's how I'd do it, with arrays and null fillers as in the question. This assumes that coords for given points always come in succession.
var arr = [['a', 'x', 1],
['a', 'y', 2],
['b', 'x', 3],
['b', 'z', 4],
['c', 'y', 5],
['c', 'z', 6]];
var aux = {
x: 1,
y: 2,
z: 3
},
output = [],
lastItem,
currItem;
for (var i = 0; i < arr.length; i++) {
currItem = arr[i];
if (currItem[0] !== lastItem) {
lastItem = currItem[0];
output.push([lastItem, null, null, null]);
}
output[output.length-1][aux[currItem[1]]] = currItem[2];
}
console.log(output); //[["a", 1, 2, null], ["b", 3, null, 4], ["c", null, 5, 6]]
Fiddle
Are you sure that's the format you want? It seems more sensible to get:
{
a: {x: 1, y: 2},
b: {x: 3, z: 4},
c: {y: 5, z: 6}
}
Which you can get from:
var results = {};
data.forEach(function(el) {
var name = el[0];
var prop = el[1];
var value = el[2];
results[name] = results[name] || {};
results[name][prop] = value;
})

a function to search array

How can I search for an element within a nested array. Following is what the array looks like
arr = [
["choice1", ['a', [2, 4]], ['b', [1, 3, 4]], ['c', [3, 4]]],
["choice2", ['b', [1, 4]], ['c', [1, 3]]],
["choice3", ['b', [1, 2, 4]], ['c', [1, 2, 3, 4]]]
]
if 'a' is equal to '2' then the following function has to return "choice1" and "choice3" in the 'result':
function arraySearch(arr, a) {
var result = [];
for(var i = 0; i < arr.length; i++) {
// compare each arr[i] with 'a' for the very first occurrence, and move the next array
if(arr[i].search(a)){
result.concat(arr[0]);
}
}
return result;
}
Please help. Many thanks in advance.
something like
arr = [
["choice1", ['a', [2, 4]], ['b', [1, 3, 4]], ['c', [3, 4]]],
["choice2", ['b', [1, 4]], ['c', [1, 3]]],
["choice3", ['b', [1, 2, 4]], ['c', [1, 2, 3, 4]]]
];
find = function(arr, a) {
var found = [];
var foundCurrent;
// for each 'choice'
for (var choice = 0; choice < arr.length; choice++) {
foundCurrent = false;
// look at each entry in the array that is arr[current][1]
for (var entry = 1; entry < arr[choice].length; entry++) {
// search these for the value
if (arr[choice][entry][1].indexOf(a) != -1) {
if (!foundCurrent) {
found[found.length] = arr[choice][0];
}
foundCurrent = true;
}
}
}
return found;
};
find(arr, 2);
>> [choice1, choice3]
It's not clear to me exactly what you need.
If you want to know whether an array contains an element, use Array.indexOf.

Categories