-5

I have the following object, and I want to put all the ids in one array.

let obj = {
    _id: 1,
    children: [
      {
        id: 2,
        children: [
          {
            id: 21,
            children: [],
          },
          {
            id: 22,
            children: [],
          },
          {
            id: 23,
            children: [
              {
                id: 231,
                children: [],
              }
            ]
          }
        ]
      },
      {
        id: 3,
        children: [
          {
            id: 31,
            children: [],
          },
          {
            id: 32,
            children: [],
            isCriteria: true
          },
          {
            id: 33,
            isCriteria: true
          }
        ]
      }
    ]
  }

I want in result:

[1, 2, 21, 22, 23, 231, 3, 31, 32, 33]

PS: the object is set dynamically, so we don't know how deep the children are.

1
  • 3
    what code did you already try? Commented Oct 16, 2019 at 10:05

5 Answers 5

2

This one is uglier, but also should be lighter on garbage collector because it does not create and spread temporary arrays.

/**
 * @param {number[]} arr Target array to which numbers will be appended
 * @param {object}   obj Source data
 * @return {number[]} arr mutated with additional numbers (if any found)
 */
function arrayAppendIdsFrom (arr, obj) {
  arr.push(obj.id);
  if (Array.isArray(obj.children) && obj.children.length > 0) {
    obj.children.forEach(child => arrayAppendIdsFrom(arr, child));
  }
      
  return arr;
}

/*
 * Example data
 */
let obj = {
  id: 1,
  children: [
    {
      id: 2,
      children: [
        {
          id: 21,
          children: [],
        },
        {
          id: 22,
          children: [],
        },
        {
          id: 23,
          children: [
            {
              id: 231,
              children: [],
            }
          ]
        }
      ]
    },
    {
      id: 3,
      children: [
        {
          id: 31,
          children: [],
        },
        {
          id: 32,
          children: [],
          isCriteria: true
        },
        {
          id: 33,
          isCriteria: true
        }
      ]
    }
  ]
};

// Example use
console.log(arrayAppendIdsFrom([], obj));

Sign up to request clarification or add additional context in comments.

Comments

2

You'll need a recursive iteration. Quick example:

let ids = [];
function getIds(obj) {

    // check for id
    if (obj.hasOwnProperty('id')) {
        ids = [...ids, obj.id];
    }

    // check for children and do recursive check
    if (obj.hasOwnProperty('children') && obj.children.length > 0) {
        obj.children.forEach(child => {
            getIds(child);
        });
    }
}

// obj here is your exmple obj with the nested structure
getIds(obj);

console.log(ids);
// [2, 21, 22, 23, 231]

Comments

1

You could use a recursive function like this:

const myObj =  obj = {
    _id: 1,
    children: [
      {
        id: 2,
        children: [
          {
            id: 21,
            children: [],
          },
          {
            id: 22,
            children: [],
          },
          {
            id: 23,
            children: [
              {
                id: 231,
                children: [],
              }
            ]
          }
        ]
      },
      {
        id: 3,
        children: [
          {
            id: 31,
            children: [],
          },
          {
            id: 32,
            children: [],
            isCriteria: true
          },
          {
            id: 33,
            isCriteria: true
          }
        ]
      }
    ]
  }

var idArray = []

function func(obj) {
  idArray.push(obj._id ? obj._id : obj.id)
  if (!obj.children) {
    return
  }

  obj.children.forEach(child => func(child))
}

func(myObj)
console.log(idArray)

Comments

1

You could create a function (fill_ids) which loop every property of obj and push into an array (ids) the values of those with key _id or id, e.g.

let ids = [];
function fill_ids(obj) {
  for (i in obj) {
    if (i == '_id' || i == 'id') {
      ids.push(obj[i]);
    } else {
      fill_ids(obj[i]);
    }
  }
}

let obj = {
  _id: 1,
  children: [{
    id: 2,
    children: [{
      id: 21,
      children: [],
    }, {
      id: 22,
      children: [],
    }, {
      id: 23,
      children: [{
        id: 231,
        children: [],
      }]
    }]
  }, {
    id: 3,
    children: [{
      id: 31,
      children: [],
    }, {
      id: 32,
      children: [],
      isCriteria: true
    }, {
      id: 33,
      isCriteria: true
    }]
  }]
};
fill_ids(obj);
console.log(ids);

Comments

0

you may use flatMap

see another example with flatDeep

    
let obj = {
    _id: 1,
    children: [
      {
        id: 2,
        children: [
          {
            id: 21,
            children: [],
          },
          {
            id: 22,
            children: [],
          },
          {
            id: 23,
            children: [
              {
                id: 231,
                children: [],
              }
            ]
          }
        ]
      },
      {
        id: 3,
        children: [
          {
            id: 31,
            children: [],
          },
          {
            id: 32,
            children: [],
            isCriteria: true
          },
          {
            id: 33,
            isCriteria: true
          }
        ]
      }
    ]
  }

function flatDeep(o) {
    return [o.id||o._id].concat( (o.children||[]).flatMap(flatDeep) );
};

console.log(flatDeep(obj));

you could remove the ||o._id and o.children||[] depending on whether your sample input was correct or approximative :)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.