1

I have a REST API from which i am fetching the json data and storing them in array. The API looks like below:

[


    {
        "id": "100",
        "name": "Person1",
        "number": "+91-8980439023"
      },
      {
        "id": "102",
        "name": "Person2",
        "number": "+91-5980339023"
      },
      {
        "id": "105",
        "name": "Person3",
        "number": "+91-8980439023"
      },
      {
        "id": "101",
        "name": "Person4",
        "number": "+91-8980439023",
        "parent": "105"
      },
      {
        "id": "110",
        "name": "Person5",
        "number": "+91-8980439023"
      },
      {
        "id": "115",
        "name": "Person6",
        "number": "+91-9834295899",
        "parent": "100"
      }
    ]

Some of the data have "parent" field.The value in the "parent" field is the "id" of the other data. Now i want to store these data which have reference in the "parent" field of other data in a separate array. For example: The data with id=101 has "parent" key with value 105 which in turn is the id of the 3rd data.So the data with id=105 should be stored in separate array.

How can i do in a simple and scalable way?

Dexygen
  • 12,287
  • 13
  • 80
  • 147
Pawan Patel
  • 195
  • 1
  • 1
  • 8
  • 1
    Use [`Array.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) to iterate over your current array. In each iteration use [`Array.find`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find) to find the parent element from the parent array, then add the found element as a property to the iterated element. – nicholaswmin Nov 28 '19 at 11:38
  • Show the expected output – Adrita Sharma Nov 28 '19 at 11:41
  • thank you for the answer.But the solution seems to have time complexity of O(n^2).Is there other solution with better time complexity?@Nik Kyriakides – Pawan Patel Nov 28 '19 at 11:41
  • Yes, transform the parents into an object with `id` as key. This will allow you to lookup if an id exists in it in constant time. I've written up an answer. – nicholaswmin Nov 28 '19 at 12:12

3 Answers3

2

Try

let parents = data.filter(d=> data.some(c=> c.parent==d.id));

let data = [
    {
        "id": "100",
        "name": "Person1",
        "number": "+91-8980439023"
      },
      {
        "id": "102",
        "name": "Person2",
        "number": "+91-5980339023"
      },
      {
        "id": "105",
        "name": "Person3",
        "number": "+91-8980439023"
      },
      {
        "id": "101",
        "name": "Person4",
        "number": "+91-8980439023",
        "parent": "105"
      },
      {
        "id": "110",
        "name": "Person5",
        "number": "+91-8980439023"
      },
      {
        "id": "115",
        "name": "Person6",
        "number": "+91-9834295899",
        "parent": "100"
      }
    ];
    
let parents = data.filter(d=> data.some(c=> c.parent==d.id));

console.log(parents);

To have O(2n) complexity first put parents id to some hash table and then filter

let data = [
    {
        "id": "100",
        "name": "Person1",
        "number": "+91-8980439023"
      },
      {
        "id": "102",
        "name": "Person2",
        "number": "+91-5980339023"
      },
      {
        "id": "105",
        "name": "Person3",
        "number": "+91-8980439023"
      },
      {
        "id": "101",
        "name": "Person4",
        "number": "+91-8980439023",
        "parent": "105"
      },
      {
        "id": "110",
        "name": "Person5",
        "number": "+91-8980439023"
      },
      {
        "id": "115",
        "name": "Person6",
        "number": "+91-9834295899",
        "parent": "100"
      }
    ];
    
let hash = {};
data.forEach(d=> hash[d.parent]=d);
let parents = data.filter(d=> d.id in hash);

console.log(parents);
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
2

You can use map method and store elements into Map collection to have O(1) when you map items:

const maps = new Map(fooArray.map(o=> [o.id, o]))
const result = fooArray.map(({parent, ...rest}) => {
    let obj = {...rest};
    parent ?  (obj.parent = [maps.get(parent)]) : null;
    return obj;
})
console.log(result);

An example:

const fooArray = [
  {
      "id": "100",
      "name": "Person1",
      "number": "+91-8980439023"
    },
    {
      "id": "102",
      "name": "Person2",
      "number": "+91-5980339023"
    },
    {
      "id": "105",
      "name": "Person3",
      "number": "+91-8980439023"
    },
    {
      "id": "101",
      "name": "Person4",
      "number": "+91-8980439023",
      "parent": "105"
    },
    {
      "id": "110",
      "name": "Person5",
      "number": "+91-8980439023"
    },
    {
      "id": "115",
      "name": "Person6",
      "number": "+91-9834295899",
      "parent": "100"
    }
  ]

const maps = new Map(fooArray.map(o=> [o.id, o]))
const result = fooArray.map(({parent, ...rest}) => {
    let obj = {...rest};
    parent ?  (obj.parent = [maps.get(parent)]) : null;
    return obj;
})
console.log(result);
StepUp
  • 36,391
  • 15
  • 88
  • 148
0

You can also collect all parent ids and then find records which has the same id as some parent:

let par_ids = [];

records.forEach(pid =>{
  for (let [key, value] of Object.entries(pid)) {
    key == 'parent' ? par_ids.push(value) : null;
  }
})

let res = records.filter(ob => par_ids.includes(ob.id))

 let records = [
          {
            "id": "100",
            "name": "Person1",
            "number": "+91-8980439023"
          },
          {
            "id": "102",
            "name": "Person2",
            "number": "+91-5980339023"
          },
          {
            "id": "105",
            "name": "Person3",
            "number": "+91-8980439023"
          },
          {
            "id": "101",
            "name": "Person4",
            "number": "+91-8980439023",
            "parent": "105"
          },
          {
            "id": "110",
            "name": "Person5",
            "number": "+91-8980439023"
          },
          {
            "id": "115",
            "name": "Person6",
            "number": "+91-9834295899",
            "parent": "100"
          }
        ];
        
let par_ids = [];

records.forEach(pid =>{
  for (let [key, value] of Object.entries(pid)) {
    key == 'parent' ? par_ids.push(value) : null;
  }
})

let res = records.filter(ob => par_ids.includes(ob.id))

console.log(res)
   
Aksen P
  • 4,564
  • 3
  • 14
  • 27
  • This is not a performant solution. The OP asked whether it's possible to avoid inner loops in the comments. – nicholaswmin Nov 28 '19 at 14:21
  • @NikKyriakides, `forEach` loop creates an array looks like your `children`. You didn't provided this step. You've took it like an input stuff, but it is not. – Aksen P Nov 28 '19 at 14:25
  • @AksenP yeah like already pointed this isnot the desirable solution.I've already tried out such approach. – Pawan Patel Nov 28 '19 at 14:43