lsgng
lsgng

Reputation: 495

Functional way to build array of arrays in JavaScript

I have a string which is the path to a value in a nested JavaScript object e.g.:

users.userA.credentials.name

I would like to split this string into its elements and then create an array with all "sub-paths", like so:

["users", "users.userA", "users.userA.credentials"]

Currently I'm solving this the following way:

const path = "users.userA.credentials.name"
const currentPath = []
const paths = []

for (const item of path.split('.')) {
  currentPath.push(item)
  paths.push([...currentPath])
}

It works fine, but I was wondering, if there is a more functional way (using map(), filter(), reduce() or maybe some lodash/ramda functions to achieve the same result.

Upvotes: 0

Views: 70

Answers (4)

Code Maniac
Code Maniac

Reputation: 37755

You can do it like this

Split the string with . and than by mapping through it we are joining the elements of temp array according to index.

let str = "users.userA.credentials.name";
let temp = str.split('.');
let op = temp.map((e,i)=> temp.slice(0,i+1).join('.'));
console.log(op);

In case you're interested to do it with regex you can do it like this

let str = "users.userA.credentials.name";
let temp = [];

let op = str.replace(/\.|$/g,(_,offset)=>{
  temp.push(str.substr(0,offset));
  return _;
})
console.log(temp);

Upvotes: 0

Hassan Imam
Hassan Imam

Reputation: 22534

You can use array#reduce. Split your path on . and then push the subarray after joining on . in an accumulator array.

const path = "users.userA.credentials.name",
      result = path.split('.').reduce((r, p, i, a) => {
        if(i)
          r.push(a.slice(0,i).join('.'));
        return r;
      }, []);
console.log(result);

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 191976

You can use Array.split() and Array.map() to do it in a more functional way:

const path = "users.userA.credentials.name"
const paths = path.split('.')
  .map((_, i, arr) => arr.slice(0, i + 1).join('.'));

console.log(paths);

Upvotes: 3

CertainPerformance
CertainPerformance

Reputation: 370729

You can use reduce to iterate over the substrings and push to an accumulator array, and check the accumulator's previous value (if any) and concatenate it with the new substring:

const path = "users.userA.credentials.name";
const splitPaths = path.split('.');
const initialValue = splitPaths.shift();
const paths = splitPaths.reduce((a, item, i) => {
  a.push(`${a[i]}.${item}`);
  return a;
}, [initialValue]);
console.log(paths);

Upvotes: 0

Related Questions