Add values of elements in array using javascript with out using const - javascript

I had an array with
0:{Name: "Test1",Cost:100,Revenue:200}
1:{Name: "Test2",Cost:100,Revenue:100}
2:{Name: "Test3",Cost:100,Revenue:300}
3:{Name: "Test2",Cost:200,Revenue:100}
4:{Name: "Test1",Cost:100,Revenue:300}
5:{Name: "Test4",Cost:100,Revenue:300}
I am expecting result with out duplicates based on names and other values (cost and revenue) as added
0:{Name: "Test1",Cost:200,Revenue:500}
1:{Name: "Test2",Cost:300,Revenue:200}
2:{Name: "Test3",Cost:100,Revenue:300}
3:{Name: "Test4",Cost:100,Revenue:300}
I am trying with below code
var removeDuplicates = function(originalArray, prop) {
var newArray = [];
var lookupObject = {};
for(var i in originalArray) {
lookupObject[originalArray[i][prop]] = originalArray[i];
}
for(i in lookupObject) {
newArray.push(lookupObject[i]);
}
return newArray;
}
console.log('Name array ',removeDuplicates(tempRoleMap, 'Name'));
Can you help me out

You can use reduce to iterate over the array while assigning to an accumulator object indexed by Name. On each array item, either assign it as the new object at that key in the accumulator if it doesn't exist yet, or iterate over the item's entries (other than Name) and add to the appropriate property in the accumulator.
At the end, you'll have an object indexed by Names, so to get the array out of the object, call Object.values on it:
const arr=[{Name:"Test1",Cost:100,Revenue:200},{Name:"Test2",Cost:100,Revenue:100},{Name:"Test3",Cost:100,Revenue:300},{Name:"Test2",Cost:200,Revenue:100},{Name:"Test1",Cost:100,Revenue:300},{Name:"Test4",Cost:100,Revenue:300}]
const result = Object.values(arr.reduce((a, { Name, ...rest }) => {
if (!a[Name]) a[Name] = { Name, ...rest };
else {
Object.entries(rest).forEach(([key, val]) => {
a[Name][key] += val;
});
}
return a;
}, {}));
console.log(result);
It's best to use ES6+ when writing code, and then you can transpile it down to ES5 automatically with Babel and polyfills. But, if you had to write in ES5, then:
var arr=[{Name:"Test1",Cost:100,Revenue:200},{Name:"Test2",Cost:100,Revenue:100},{Name:"Test3",Cost:100,Revenue:300},{Name:"Test2",Cost:200,Revenue:100},{Name:"Test1",Cost:100,Revenue:300},{Name:"Test4",Cost:100,Revenue:300}]
var obj = arr.reduce(function(a, item) {
var Name = item.Name;
if (!a[Name]) a[Name] = item;
else {
Object.keys(item).forEach(function(key) {
if (key === 'Name') return;
a[Name][key] += item[key];
});
}
return a;
}, {});
var output = [];
Object.keys(obj).forEach(function(key) {
output.push(obj[key]);
});
console.log(output);
As you can see, it's a whole lot wordier and inelegant - better to write in the latest and greatest version of the language, and transpile down to your target environment automatically later.

You can get the desired output using .reduce() and Object.values():
let data = [
{Name: "Test1", Cost:100, Revenue:200},
{Name: "Test2", Cost:100, Revenue:100},
{Name: "Test3", Cost:100, Revenue:300},
{Name: "Test2", Cost:200, Revenue:100},
{Name: "Test1", Cost:100, Revenue:300},
{Name: "Test4", Cost:100, Revenue:300}
];
let result = Object.values(
data.reduce((r, c) => {
r[c.Name] = r[c.Name] || {};
r[c.Name].Cost = (r[c.Name].Cost || 0) + c.Cost;
r[c.Name].Revenue = (r[c.Name].Revenue || 0) + c.Revenue;
return r;
}, {})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You will find a solution in the snippet below:
var arr = [{Name: "Test1",Cost:100,Revenue:200},
{Name: "Test2",Cost:100,Revenue:100},
{Name: "Test3",Cost:100,Revenue:300},
{Name: "Test2",Cost:200,Revenue:100},
{Name: "Test1",Cost:100,Revenue:300},
{Name: "Test4",Cost:100,Revenue:300}];
function removeDuplicates(arr, prop){
arr.forEach((a, i) => arr.slice(i+1).filter(e => e[prop] == a[prop]).forEach( el => {
if (arr.indexOf(el) > -1)
arr.splice(arr.indexOf(el), 1);
}));
return arr;
}
console.log(removeDuplicates(arr, 'Name'));

Related

Can I add or edit object in array by field [duplicate]

I have this javascript object:
var arr1 = [{id:'124',name:'qqq'},
{id:'589',name:'www'},
{id:'45',name:'eee'},
{id:'567',name:'rrr'}]
var arr2 = [{id:'124',name:'ttt'},
{id:'45',name:'yyy'}]
I need to replace objects in arr1 with items from arr2 with same id.
So here is the result I want to get:
var arr1 = [{id:'124',name:'ttt'},
{id:'589',name:'www'},
{id:'45',name:'yyy'},
{id:'567',name:'rrr'}]
How can I implement it using javascript?
You can use Array#map with Array#find.
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
var arr1 = [{
id: '124',
name: 'qqq'
}, {
id: '589',
name: 'www'
}, {
id: '45',
name: 'eee'
}, {
id: '567',
name: 'rrr'
}];
var arr2 = [{
id: '124',
name: 'ttt'
}, {
id: '45',
name: 'yyy'
}];
var res = arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
console.log(res);
Here, arr2.find(o => o.id === obj.id) will return the element i.e. object from arr2 if the id is found in the arr2. If not, then the same element in arr1 i.e. obj is returned.
What's wrong with Object.assign(target, source) ?
Arrays are still type object in Javascript, so using assign should still reassign any matching keys parsed by the operator as long as matching keys are found, right?
There is always going to be a good debate on time vs space, however these days I've found using space is better for the long run.. Mathematics aside let look at a one practical approach to the problem using hashmaps, dictionaries, or associative array's whatever you feel like labeling the simple data structure..
var marr2 = new Map(arr2.map(e => [e.id, e]));
arr1.map(obj => marr2.has(obj.id) ? marr2.get(obj.id) : obj);
I like this approach because though you could argue with an array with low numbers you are wasting space because an inline approach like #Tushar approach performs indistinguishably close to this method. However I ran some tests and the graph shows how performant in ms both methods perform from n 0 - 1000. You can decide which method works best for you, for your situation but in my experience users don't care to much about small space but they do care about small speed.
Here is my performance test I ran for source of data
var n = 1000;
var graph = new Array();
for( var x = 0; x < n; x++){
var arr1s = [...Array(x).keys()];
var arr2s = arr1s.filter( e => Math.random() > .5);
var arr1 = arr1s.map(e => {return {id: e, name: 'bill'}});
var arr2 = arr2s.map(e => {return {id: e, name: 'larry'}});
// Map 1
performance.mark('p1s');
var marr2 = new Map(arr2.map(e => [e.id, e]));
arr1.map(obj => marr2.has(obj.id) ? marr2.get(obj.id) : obj);
performance.mark('p1e');
// Map 2
performance.mark('p2s');
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
performance.mark('p2e');
graph.push({ x: x, r1: performance.measure('HashMap Method', 'p1s', 'p1e').duration, r2: performance.measure('Inner Find', 'p2s','p2e').duration});
}
Since you're using Lodash you could use _.map and _.find to make sure major browsers are supported.
In the end I would go with something like:
function mergeById(arr) {
return {
with: function(arr2) {
return _.map(arr, item => {
return _.find(arr2, obj => obj.id === item.id) || item
})
}
}
}
var result = mergeById([{id:'124',name:'qqq'},
{id:'589',name:'www'},
{id:'45',name:'eee'},
{id:'567',name:'rrr'}])
.with([{id:'124',name:'ttt'}, {id:'45',name:'yyy'}])
console.log(result);
<script src="https://raw.githubusercontent.com/lodash/lodash/4.13.1/dist/lodash.js"></script>
Thanks to ES6 we can made it with easy way -> for example on util.js module ;))).
Merge 2 array of entity
export const mergeArrays = (arr1, arr2) =>
arr1 && arr1.map(obj => arr2 && arr2.find(p => p.id === obj.id) || obj);
gets 2 array and merges it.. Arr1 is main array which is priority is
high on merge process
Merge array with same type of entity
export const mergeArrayWithObject = (arr, obj) => arr && arr.map(t => t.id === obj.id ? obj : t);
it merges the same kind of array of type with some kind of type for
example: array of person ->
[{id:1, name:"Bir"},{id:2, name: "Iki"},{id:3, name:"Uc"}]
second param Person {id:3, name: "Name changed"}
result is
[{id:1, name:"Bir"},{id:2, name: "Iki"},{id:3, name:"Name changed"}]
I like to go through arr2 with foreach() and use findIndex() for checking for occurrence in arr1:
var arr1 = [{id:'124',name:'qqq'},
{id:'589',name:'www'},
{id:'45',name:'eee'},
{id:'567',name:'rrr'}]
var arr2 = [{id:'124',name:'ttt'},
{id:'45',name:'yyy'}]
arr2.forEach(element => {
const itemIndex = arr1.findIndex(o => o.id === element.id);
if(itemIndex > -1) {
arr1[itemIndex] = element;
} else {
arr1 = arr1.push(element);
}
});
console.log(arr1)
I'd like to suggest another solution:
const objectToReplace = this.array.find(arrayItem => arrayItem.id === requiredItem.id);
Object.assign(objectToReplace, newObject);
Considering that the accepted answer is probably inefficient for large arrays, O(nm), I usually prefer this approach, O(2n + 2m):
function mergeArrays(arr1 = [], arr2 = []){
//Creates an object map of id to object in arr1
const arr1Map = arr1.reduce((acc, o) => {
acc[o.id] = o;
return acc;
}, {});
//Updates the object with corresponding id in arr1Map from arr2,
//creates a new object if none exists (upsert)
arr2.forEach(o => {
arr1Map[o.id] = o;
});
//Return the merged values in arr1Map as an array
return Object.values(arr1Map);
}
Unit test:
it('Merges two arrays using id as the key', () => {
var arr1 = [{id:'124',name:'qqq'}, {id:'589',name:'www'}, {id:'45',name:'eee'}, {id:'567',name:'rrr'}];
var arr2 = [{id:'124',name:'ttt'}, {id:'45',name:'yyy'}];
const actual = mergeArrays(arr1, arr2);
const expected = [{id:'124',name:'ttt'}, {id:'589',name:'www'}, {id:'45',name:'yyy'}, {id:'567',name:'rrr'}];
expect(actual.sort((a, b) => (a.id < b.id)? -1: 1)).toEqual(expected.sort((a, b) => (a.id < b.id)? -1: 1));
})
// here find all the items that are not it the arr1
const temp = arr1.filter(obj1 => !arr2.some(obj2 => obj1.id === obj2.id))
// then just concat it
arr1 = [...temp, ...arr2]
Here a more transparent approach. I find the oneliners harder to read and harder to debug.
export class List {
static replace = (object, list) => {
let newList = [];
list.forEach(function (item) {
if (item.id === object.id) {
newList.push(object);
} else {
newList.push(item);
}
});
return newList;
}
}
If you don't care about the order of the array, then you may want to get the difference between arr1 and arr2 by id using differenceBy() and then simply use concat() to append all the updated objects.
var result = _(arr1).differenceBy(arr2, 'id').concat(arr2).value();
var arr1 = [{
id: '124',
name: 'qqq'
}, {
id: '589',
name: 'www'
}, {
id: '45',
name: 'eee'
}, {
id: '567',
name: 'rrr'
}]
var arr2 = [{
id: '124',
name: 'ttt'
}, {
id: '45',
name: 'yyy'
}];
var result = _(arr1).differenceBy(arr2, 'id').concat(arr2).value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.js"></script>
I am only submitting this answer because people expressed concerns over browsers and maintaining the order of objects. I recognize that it is not the most efficient way to accomplish the goal.
Having said this, I broke the problem down into two functions for readability.
// The following function is used for each itertion in the function updateObjectsInArr
const newObjInInitialArr = function(initialArr, newObject) {
let id = newObject.id;
let newArr = [];
for (let i = 0; i < initialArr.length; i++) {
if (id === initialArr[i].id) {
newArr.push(newObject);
} else {
newArr.push(initialArr[i]);
}
}
return newArr;
};
const updateObjectsInArr = function(initialArr, newArr) {
let finalUpdatedArr = initialArr;
for (let i = 0; i < newArr.length; i++) {
finalUpdatedArr = newObjInInitialArr(finalUpdatedArr, newArr[i]);
}
return finalUpdatedArr
}
const revisedArr = updateObjectsInArr(arr1, arr2);
jsfiddle
function getMatch(elem) {
function action(ele, val) {
if(ele === val){
elem = arr2[i];
}
}
for (var i = 0; i < arr2.length; i++) {
action(elem.id, Object.values(arr2[i])[0]);
}
return elem;
}
var modified = arr1.map(getMatch);
I went with this, because it makes sense to me. Comments added for readers!
masterData = [{id: 1, name: "aaaaaaaaaaa"},
{id: 2, name: "Bill"},
{id: 3, name: "ccccccccc"}];
updatedData = [{id: 3, name: "Cat"},
{id: 1, name: "Apple"}];
updatedData.forEach(updatedObj=> {
// For every updatedData object (dataObj), find the array index in masterData where the IDs match.
let indexInMasterData = masterData.map(masterDataObj => masterDataObj.id).indexOf(updatedObj.id); // First make an array of IDs, to use indexOf().
// If there is a matching ID (and thus an index), replace the existing object in masterData with the updatedData's object.
if (indexInMasterData !== undefined) masterData.splice(indexInMasterData, 1, updatedObj);
});
/* masterData becomes [{id: 1, name: "Apple"},
{id: 2, name: "Bill"},
{id: 3, name: "Cat"}]; as you want.`*/
The accepted answer using array.map is correct but you have to remember to assign it to another variable since array.map doesnt change original array, it actually creates a new array.
//newArr contains the mapped array from arr2 to arr1.
//arr1 still contains original value
var newArr = arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
Array.prototype.update = function(...args) {
return this.map(x=>args.find((c)=>{return c.id===x.id}) || x)
}
const result =
[
{id:'1',name:'test1'},
{id:'2',name:'test2'},
{id:'3',name:'test3'},
{id:'4',name:'test4'}
]
.update({id:'1',name:'test1.1'}, {id:'3',name:'test3.3'})
console.log(result)
This is how I do it in TypeScript:
const index = this.array.indexOf(this.objectToReplace);
this.array[index] = newObject;

Mark only second duplicated object in js array

I have a list of objects:
[{name: 'Elza'}, {name: 'Tom'}, {name: 'Elza'}]
I use the below methods to get duplicated objects(by name) and assign a prop isDuplicated:
const duplicatedNames = arrayOfObjects
.map(e => e['name'])
.map((e, i, final) => final.indexOf(e) !== i && i++)
.filter(obj => arrayOfObjects[obj])
.map(e => !arrayOfObjects[e]['name']);
const result = arrayOfObjects.filter((obj, i) => {
return duplicatedNames.includes(obj.name) && Object.assign(obj, { isDuplicated: true });
});
I receive an array like:
[{name: 'Elza', isDuplicated: true}, {name: 'Tom'}, {name: 'Elza', isDuplicated: true}]
I would like to mark only the second occurrence of duplicate- so i would like the result to be:
[{name: 'Elza'}, {name: 'Tom'}, {name: 'Elza', isDuplicated: true}]
Can anyone know how to do it base on my code?
Here is a function that checks if a name exist more then once.
let data = [{name:'Elza'}, {name:'Tom'}, {name:'Elza'}, {name: "Jerry"}, {name: "Jerry"}];
function checkDup(arr){
let cache = [];
return arr.map(({name}, index) => {
if(!cache.find(el => el.name == name)){
cache.push({name, index});
return {name, index};
}
let { index: cacheIndex } = cache.find(el => el.name === name);
return {name,index: cacheIndex , isDuplicated: true};
})
}
console.log(checkDup(data));
You could create a Set of names. If the size of the set is same as after the name has been added, then it's duplicate record.
const input = [{name:'Elza'}, {name:'Tom'}, {name:'Elza'}],
names = new Set;
for (const o of input)
if (names.size === names.add(o.name).size)
o.isDuplicate = true
console.log(input)
You can try this:
let users = [{name:'Elza'}, {name:'Tom'}, {name:'Elza'}]
let flags = [], output = [];
users.forEach(user => {
if (flags[user.name]) {
output.forEach(item => {
if (item.name === user.name) {
item.isDuplicated = true
output.push(user);
}
})
} else {
flags[user.name] = true;
output.push(user);
}
})
Given your original array A, you could create a temporary array B and, for each a element of A, check:
if B contains a.name, then set a.isDuplicated to true;
else, push a.name in B.
let A = [{name: 'Elza'}, {name: 'Tom'}, {name: 'Elza'}];
let B = [];
A.forEach(a => {
if (B.includes(a.name)) {
a.isDuplicated = true;
} else {
B.push(a.name);
}
});
console.log(A);
You can use reduce with a helper object:
const collection = [{ name: 'Elza'}, { name: 'Tom'}, { name: 'Elza' }]
const helper = {}
const result = collection.reduce((acc, { name }) => {
if (helper[name]) {
return [...acc, { name, isDuplicate: true }]
}
helper[name] = 'x';
return [...acc, { name }]
}, [])
console.log(result)

Split an object in to array of objects based on similar values

var pr = {
name: "ball",
race: "ball",
weapon: "axe",
};
var save=new Object;
var keys=Object.keys(pr);
for(var k in pr) {
}
console.log(save); // should end up with {name:'ball',race:'ball'}
If I have understood the question correctly, one option is:
const keys = Object.keys(pr);
const ret = keys.reduce((ret, k, i) => {
const f = keys.find((k2, i2) => i !== i2 && pr[k] === pr[k2]);
if (f) ret[k] = pr[k];
return ret;
}, {});
Here is what I came up with.
var pr = {
name: "ball",
race: "ball",
weapon: "axe"
};
const dupValues = Object.values(pr).reduce(
(acc, cur) => ({ ...acc, [cur]: (acc[cur] || 0) + 1 }),
{}
);
const result = Object.keys(pr)
.filter(key => dupValues[pr[key]] > 1)
.reduce((acc, curr) => ({ ...acc, [curr]: pr[curr] }), {});
console.log(result);
// {name:'ball',race:'ball'}
One way to do it is use the save object as a histogram, keeping track of duplicates. Then, filter out any keys with 0 count using reduce. This should have better performance than a linear function like find:
var pr = {
name: "ball",
race: "ball",
weapon: "axe"
};
var save = {};
for (var k in pr) {
save[pr[k]] = pr[k] in save ? save[pr[k]] + 1 : 0;
}
var result = Object.keys(pr).reduce((a, e) => {
if (save[pr[e]]) { a[e] = pr[e]; }
return a;
}, {});
console.log(result);
It works. Simple and clear. References : Array.reduce()
Iterate through each key value pair, and accumulate the result until the loop ends.
var pr = {
name: "ball",
race: "ball",
weapon: "axe",
item:"bat",
newitem:"bat",
newweapon: "axe"
};
var result = Object.keys(pr).reduce(function(acc, key){
var ispresent = false;
acc.forEach(function(obj,i){
if(ispresent) return;
if(Object.values(obj)[0]===pr[key])
{
obj[key]=pr[key];
ispresent = true;
}
});
if(!ispresent)
{
var newobj = {};newobj[key]=pr[key];
acc.push(newobj)
}
return acc;
},[])
console.log(result)

How to merge values from multiple objects into an object of arrays?

I have a two JSON something like below:
var obj1 = {
" name ":"rencho",
" age ":23,
" occupation ":"SE"
}
var obj2 = {
" name ":"manu",
" age ":23,
" country ":"india"
}
I want the expected output:
var result = {
"name":["rencho", "manu"],
"age":[23, 23],
"country":["-", "india"],
"occupation": ["SE", "-"],
}
However, I tried using below the code snippet:
let arrGlobal = []
arrGlobal.push(obj1);
arrGlobal.push(obj2);
let mergedResult = arrGlobal.reduce(function(r, e) {
return Object.keys(e).forEach(function(k) {
if(!r[k]) r[k] = [].concat(e[k])
else r[k] = r[k].concat(e[k])
}), r
}, {})
console.log(mergedResult);
But that one doesn't print - in json object. I would appreciate any kind of help from your side.
HELP WOULD BE APPRECIATED!!!
First get a list of all keys (needed in advance to check whether you need to add - while iterating), then use reduce to iterate over each object and add its values to the accumulator:
var obj1 = {
" name ":"rencho",
" age ":23,
" occupation ":"SE"
}
var obj2 = {
" name ":"manu",
" age ":23,
" country ":"india"
}
const arr = [obj1, obj2];
const allKeys = arr.reduce((keys, obj) => {
Object.keys(obj).forEach(key => keys.add(key))
return keys;
}, new Set());
const merged = arr.reduce((merged, obj) => {
allKeys.forEach((key) => {
if (!merged[key]) merged[key] = [];
merged[key].push(obj[key] || '-');
});
return merged;
}, {});
console.log(merged);
A slightly different approach by using a single loop for the outer array of objects and which generates all needed keys on the fly.
var obj1 = { name: "rencho", age: 23, occupation: "SE" },
obj2 = { name: "manu", age: 23, country: "india" },
hash = new Set,
result = {};
[obj1, obj2].forEach((o, length) => {
Object.keys(o).forEach(k => hash.add(k));
hash.forEach(k => {
result[k] = result[k] || Array.from({ length }).fill('-');
result[k].push(k in o ? o[k] : '-');
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
quick and dirty way:
function merge(a,b) {
var c = b
for (key in a){
c[key] = [c[key], a[key]]
}
console.log(c) //prints merged object
}
merge(obj1, obj2)

Transform an array to an object with nested properties according to the array

I have several arrays as the following:
[ 'businessOpenAccount', 'accountSettings1.page.js' ]
[ 'businessOpenAccount', 'accountSettings2.page.js' ]
[ 'mainTest', 'test', 'test1.page.js' ]
[ 'mainTest', 'test', 'test2.page.js' ]
My expected result is to have an object in this way:
{
businessOpenAccount: {
'accountSettings1.page.js': {},
'accountSettings2.page.js': {}
},
mainTest: {
test: {
'test1.page.js': {},
'test2.page.js': {}
}
}
}
So actually I want to parse the arrays and build a nested object to return from them, but being sure to check that if a property already exists (because defined from a previous array) I won't override it, but just add the new nested property in it, respecting the correct order of nesting.
I tried few approaches using reduce, reduceRight and simple forEach/for loops but I still cannot really achieve the solution I would like.
Any tips please?
This is the best way I have so far, but I override the properties cycling over multiple arrays (the example with a single array):
const relevantFilePath = ['businessOpenAccount', 'accountSettings.page.js'];
let obj = {};
relevantFilePath.forEach((el, ind) => {
if (ind === 0) {
obj[el] = {};
previousEl = obj[el];
} else {
previousEl[el] = {};
previousEl = previousEl[el];
}
});
console.log(obj);
You could iterate the given data and reduce the object and take the last item with splitted value.
var data = [['businessOpenAccount', 'accountSettings1.page.js'], ['businessOpenAccount', 'accountSettings2.page.js'], ['mainTest', 'test', 'test1.page.js'], ['mainTest', 'test', 'test2.page.js']],
object = {};
data.forEach(function (a) {
var last = a.pop().split('.')[0];
a.reduce(function (o, k) {
return o[k] = o[k] || {};
}, object)[last] = '';
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
ES6 with without mutating original data
var data = [['businessOpenAccount', 'accountSettings1.page.js'], ['businessOpenAccount', 'accountSettings2.page.js'], ['mainTest', 'test', 'test1.page.js'], ['mainTest', 'test', 'test2.page.js']],
object = {};
data.forEach(function (a) {
var temp = a.slice(),
last = temp.pop().split('.')[0];
temp.reduce((o, k) => o[k] = o[k] || {}, object)[last] = '';
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
A recursive solution which would work for anykind of sub array with unlimited depth.
const a = [
['businessOpenAccount', 'accountSettings1.page.js'],
['businessOpenAccount', 'accountSettings2.page.js'],
[ 'businessOpenAccount', 'test1',
[
['test2', 'test2.settings.page.js',
[
['test2', 'test2.settings.page.js'],
['test3', 'test3.settings.page.js'],
],
'test4',
],
['test3', 'test3.settings.page.js'],
]
],
['mainTest', 'test', 'test1.page.js'],
['mainTest', 'test', 'test2.page.js'],
];
const result = {};
const traverse = (result, arr) => {
let firstEl = arr.shift();
if (firstEl instanceof Array) {
if (arr.length >= 1) {
traverseTop(result, firstEl);
return traverse(result, arr);
}
return traverseTop(result, firstEl);
}
firstEl = firstEl.split('.')[0];
result[firstEl] = arr.length >= 1 ? (result[firstEl] || {}) : '';
if (arr.length >= 1) {
return traverse(result[firstEl], arr);
}
return;
};
const traverseTop = (result, arr) => {
arr.forEach((subArr) => {
const firstEl = subArr.shift().split('.')[0];
result[firstEl] = result[firstEl] || {};
traverse(result[firstEl], subArr)
});
return result;
};
console.log(traverseTop(result, a));

Categories

Resources