Search array of nested objects with dynamic parameters

Viewed 77

I have an array with objects. I'm trying to recursively search through them and create new array with modified key's.

The array:

    let response = {
    users: [
        {
            user_id: 1661871600,
            details: {
                height: 150,
                age: 33,
                work: 1015,
                school: 10,
                degree: 933
            },
            work: [
                {
                    id: 500,
                    main: 'Doctor',
                    description: 'Ofto',
                    icon: '10d',
                },
            ],
            look: {
                all: 100,
            },
            transport: {
                speed: 0.62,
                max_speed: 349,
            },
            visibility: 10000,
            hair: {
                type: 0.26,
            },
            date: '2022-08-30 15:00:00',
        },
        {
            user_id: 324235256,
            details: {
                height: 110,
                age: 25,
                work: 101,
                school: 110,
                degree: 553
            },
            work: [
                {
                    id: 500,
                    main: 'Software',
                    description: 'Programmer',
                    icon: '11d',
                },
            ],
            look: {
                all: 2,
            },
            transport: {
                speed: 1.2,
                max_speed: 49,
            },
            visibility: 221,
            hair: {
                type: 5.6,
            },
            date: '2021-01-30 12:00:00',
        },
        {
            user_id: 12353743,
            details: {
                height: 10,
                age: 75,
                work: 1,
                school: 114,
                degree: 3
            },
            work: [
                {
                    id: 500,
                    main: 'Pension',
                    description: 'Architect',
                    icon: '1d',
                },
            ],
            look: {
                all: 6,
            },
            transport: {
                speed: 3.2,
                max_speed: 29,
            },
            visibility: 21,
            hair: {
                type: 1.6,
            },
            date: '2020-01-30 12:00:00',
        },
    ],
};

I've tried using JSON.Stringify but I keep getting not desired result.

    function dynamic(obj, ...keyToFind) {
    const foundObj = {};
    const foundObjArray: any[] = [];
    keyToFind.forEach((key) => {
        JSON.stringify(obj, (_, nestedValue) => {
            if (nestedValue && nestedValue[a]) {
                foundObj[key] = nestedValue[a];
            }
            return nestedValue;
        });
        foundObjArray.push(foundObj);
    });
    return foundObjArray;
}

I'm calling this function with N number of parameters:

dynamic(response, 'age', 'work', 'main', 'description', 'type', 'date');

Once it is called I'm trying to construct a new array of objects who will look like:

let foundObjArray = [
   {
     'age': 33,
     'work': 1015,
     'main': 'Doctor',
     'description': 'Ofto',
     'type': 5.6,
     'date': '2022-08-30 15:00:00'
   },
   {
     'age': 25,
     'work': 101,
     'main': 'Software',
     'description': 'Programmer',
     'type': 0.26,
     'date': '2021-01-30 12:00:00'
   },
   .......
]
3 Answers

let response = {
    users: [
        {
            user_id: 1661871600,
            details: {
                height: 150,
                age: 33,
                speed_min: 296.76,
                speed_max: 297.87,
                work: 1015,
                school: 10,
                degree: 933
            },
            work: [
                {
                    id: 500,
                    main: 'Doctor',
                    description: 'Ofto',
                    icon: '10d',
                },
            ],
            look: {
                all: 100,
            },
            transport: {
                speed: 0.62,
                max_speed: 349,
            },
            visibility: 10000,
            hair: {
                type: 0.26,
            },
            date: '2022-08-30 15:00:00',
        },
        {
            user_id: 324235256,
            details: {
                height: 110,
                age: 25,
                speed_min: 96.76,
                speed_max: 327.87,
                work: 101,
                school: 110,
                degree: 553
            },
            work: [
                {
                    id: 500,
                    main: 'Software',
                    description: 'Programmer',
                    icon: '11d',
                },
            ],
            look: {
                all: 2,
            },
            transport: {
                speed: 1.2,
                max_speed: 49,
            },
            visibility: 221,
            hair: {
                type: 5.6,
            },
            date: '2021-01-30 12:00:00',
        },
        {
            user_id: 12353743,
            details: {
                height: 10,
                age: 75,
                speed_min: 16.76,
                speed_max: 27.87,
                work: 1,
                school: 114,
                degree: 3
            },
            work: [
                {
                    id: 500,
                    main: 'Pension',
                    description: 'Architect',
                    icon: '1d',
                },
            ],
            look: {
                all: 6,
            },
            transport: {
                speed: 3.2,
                max_speed: 29,
            },
            visibility: 21,
            hair: {
                type: 1.6,
            },
            date: '2020-01-30 12:00:00',
        },
    ],
};

function getMatchedKey(arr, key) {
    let matched = arr.filter(x => key.endsWith(x));
    if(matched.length > 0) {
        return matched[0];
    }
}

function getLimitedData(data, requiredKey = []) {
    var result = {};
    function recurse(cur, prop) {
        if (Object(cur) !== cur) {
            let matchedKey = getMatchedKey(requiredKey, prop);
            matchedKey != undefined && (result[matchedKey] = cur);
        } else if (Array.isArray(cur)) {
            for (var i = 0, l = cur.length; i < l; i++)
                recurse(cur[i], prop + "[" + i + "]");
            if (l == 0) {
                let matchedKey = getMatchedKey(requiredKey, prop);
                matchedKey != undefined && (result[matchedKey] = []);
            }
        } else {
            var isEmpty = true;
            for (var p in cur) {
                isEmpty = false;
                recurse(cur[p], prop ? prop + "." + p : p);
            }
            if (isEmpty && prop) {
                let matchedKey = getMatchedKey(requiredKey, prop);
                matchedKey != undefined && (result[matchedKey] = {});
            }
        }
    }
    recurse(data, "");
    return result;
}

let keys = ['age', 'work', 'main', 'description', 'type', 'date'];
let output = response.users.map(a => getLimitedData(a, keys));
console.log(output);

A JSON.stringify based approach, as initially intended by the OP, is even a reliable one, in case one wants to target any user-item's first occurring entry regardless of its nesting level/depth where each property's value is not of object or array type itself.

One just needs to come up with an according property specific regex like e.g. for the "work" key ... /"work":(?<value>[^\[{]+?)(?=,"|\})/.

The rest then can be achieved by combined map and reduce tasks, where with each item's mapping a new object is created via reducing an array of property names which has to be provided as the map method's 2nd thisArg parameter.

const response = {
  users: [{
    user_id: 1661871600,
    details: {
      height: 150,
      age: 33,
      work: 1015,
      school: 10,
      degree: 933
    },
    work: [{
      id: 500,
      main: 'Doctor',
      description: 'Ofto',
      icon: '10d',
    }],
    look: {
      all: 100,
    },
    transport: {
      speed: 0.62,
      max_speed: 349,
    },
    visibility: 10000,
    hair: {
      type: 0.26,
    },
    date: '2022-08-30 15:00:00',
  }, {
    user_id: 324235256,
    details: {
      height: 110,
      age: 25,
      work: 101,
      school: 110,
      degree: 553
    },
    work: [{
      id: 500,
      main: 'Software',
      description: 'Programmer',
      icon: '11d',
    }],
    look: {
      all: 2,
    },
    transport: {
      speed: 1.2,
      max_speed: 49,
    },
    visibility: 221,
    hair: {
      type: 5.6,
    },
    date: '2021-01-30 12:00:00',
  }, {
    user_id: 12353743,
    details: {
      height: 10,
      age: 75,
      work: 1,
      school: 114,
      degree: 3
    },
    work: [{
      id: 500,
      main: 'Pension',
      description: 'Architect',
      icon: '1d',
    }],
    look: {
      all: 6,
    },
    transport: {
      speed: 3.2,
      max_speed: 29,
    },
    visibility: 21,
    hair: {
      type: 1.6,
    },
    date: '2020-01-30 12:00:00',
  }],
};

function createObjectOfFirstOccurringValuesFromBoundKeyList(item) {
  const itemData = JSON.stringify(item);
  return this // `this` equals the bound array of property names.
    .reduce((result, key) => {

      const { value = null } =
        RegExp(`"${ key }":(?<value>[^\[{]+?)(?=,"|\})`)
          // see ... [https://regex101.com/r/ss6jlt/1]
          .exec(itemData)
          ?.groups ?? {};

      if (value !== null) {
        Object
          .assign(result, { [key]: JSON.parse(value) });
      }
      return result;

    }, {})
}

const listOfFirstPropertyValueItems = response
  .users
  .map(createObjectOfFirstOccurringValuesFromBoundKeyList, [
    'age', 'work', 'main', 'description', 'type', 'date'
  ]);

console.log({
  listOfFirstPropertyValueItems
});
.as-console-wrapper { min-height: 100%!important; top: 0; }

you can do like this two by saperating objectFunction and ArrayFunction recursively

 

let keys = ['age', 'work', 'main', 'description', 'type', 'date'];

     let response = {
        users: [
            {
                user_id: 1661871600,
                details: {
                    height: 150,
                    age: 33,
                    work: 1015,
                    school: 10,
                    degree: 933
                },
                work: [
                    {
                        id: 500,
                        main: 'Doctor',
                        description: 'Ofto',
                        icon: '10d',
                    },
                ],
                look: {
                    all: 100,
                },
                transport: {
                    speed: 0.62,
                    max_speed: 349,
                },
                visibility: 10000,
                hair: {
                    type: 0.26,
                },
                date: '2022-08-30 15:00:00',
            },
            {
                user_id: 324235256,
                details: {
                    height: 110,
                    age: 25,
                    work: 101,
                    school: 110,
                    degree: 553
                },
                work: [
                    {
                        id: 500,
                        main: 'Software',
                        description: 'Programmer',
                        icon: '11d',
                    },
                ],
                look: {
                    all: 2,
                },
                transport: {
                    speed: 1.2,
                    max_speed: 49,
                },
                visibility: 221,
                hair: {
                    type: 5.6,
                },
                date: '2021-01-30 12:00:00',
            },
            {
                user_id: 12353743,
                details: {
                    height: 10,
                    age: 75,
                    work: 1,
                    school: 114,
                    degree: 3
                },
                work: [
                    {
                        id: 500,
                        main: 'Pension',
                        description: 'Architect',
                        icon: '1d',
                    },
                ],
                look: {
                    all: 6,
                },
                transport: {
                    speed: 3.2,
                    max_speed: 29,
                },
                visibility: 21,
                hair: {
                    type: 1.6,
                },
                date: '2020-01-30 12:00:00',
            },
        ],
    };
// main function
const fun =(ob, k , con)=>{
    // recursive object function  
     const objectFun =(arr)=>{
         for(y in arr){
         if(typeof arr[y] === "object"){
            objectFun(arr[y])
          }else if(Array.isArray(arr[y])){
            arrayFun(arr[y])
          }else if(k.includes(y)){
           temp[y] = arr[y]
          }}}

     // recursive array function
     const arrayFun =(xx) =>{
          const usersList = ob[xx].map((ar, i)=>{
          objectFun(ar)
          con.push(temp)
          temp ={}
          })}

      // main access key for in loop
    for(x in ob){
        var temp = {}
         arrayFun(x)
    }
       return con
    }
    console.log(fun(response , keys , []))
.as-console-wrapper { min-height: 100%!important; top: 0; }

Related