Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript - return parent with only child that matches given search string in array of objects with nested object

This is a follow up question from my previous question. From the answer I've received, I am able to search within nested object in an array of objects.

Please find this fiddle for example.

var data = [
{
  'booking_name': 'gtec/1101822/lmikdy/ls-rmea/oss11',
  'asset_count': 2,
  'pdg': 'Invalid',
  'user_area': 'Invalid',
  'deployment_number': 'Invalid',
  'spoc': 'invalid',
  'release': 'Invalid',
  'start_date': '2017-06-12 00:00:00',
  'end_date': '2017-06-16 00:00:00',
  'asset_info': [
    {
      'bams_id': 'BAMS-1001423507',
      'hostname': 'GTVOSS11',
      'status': 10,
      'site_location': 'IEAT01 Tipperary',
      'rack_number': 'VIRTUAL RACK',
      'rack_u_position': 0,
      'manufacturer': 'EMC',
      'model': 'VM',
      
    },
    {
      'bams_id': 'BAMS-1001368001',
      'hostname': 'None',
      'status': 10,
      'site_location': 'IEAT01 Tipperary',
      'rack_number': 'VIRTUAL RACK',
      'rack_u_position': 0,
      'manufacturer': 'HP',
      'model': 'HP BL460C GEN8',
      
    }
],
'full_name': 'Invalid (invalid)',
'email_address': 'Invalid'
},
{
  'booking_name': 'gtec/1101822/lmikdy/ls-rmea/oss11',
  'asset_count': 2,
  'pdg': 'Invalid',
  'user_area': 'Invalid',
  'deployment_number': 'Invalid',
  'spoc': 'invalid',
  'release': 'Invalid',
  'start_date': '2017-06-12 00:00:00',
  'end_date': '2017-06-16 00:00:00',
  'asset_info': [
    {
      'bams_id': 'BAMS-1001423507',
      'hostname': 'GTVOSS11',
      'status': 10,
      'site_location': 'IEAT01 Tipperary',
      'rack_number': 'VIRTUAL RACK',
      'rack_u_position': 0,
      'manufacturer': 'EMC',
      'model': 'VM',
      
    }
],
'full_name': 'Invalid (invalid)',
'email_address': 'Invalid'
}];

Here when I search for a string 'emc', the function returns two objects which is correct. But 'emc' as 'manufacturer' is in child object. And every child object does not satisfies this condition. The result I am looking for, for example 'emc', it should return 2 parent objects. First parent object should have only one child (the other child has 'hp' as manufacturer). Second parent object should have one child as it matches the search string.

I tried to make a new object with search result but couldn't make it work.

How do I return parent object with only child that satisfies the given search string ?

Here is the chatlog on my previous question which can help to understand the problem and requirement.

like image 735
Valay Avatar asked Feb 15 '26 05:02

Valay


2 Answers

You could use an iterative and recursive approach and return the result of the check and build new objects and arrays if the children matches the search value.

function getValue(item) {
    if (Array.isArray(item)) {
        return item.reduce(iterA, undefined);
    }
    if (item && typeof item === 'object') {
        return iterO(item);
    }
    if (typeof item !== 'object' && item.toString().toLowerCase().indexOf(search) !== -1) {
        return item;
    }
}

function iterO(o) {
    var temp = Object.keys(o).reduce(function (r, k) {
            var value = getValue(o[k]);
            if (value) {
                r = r || {};
                r[k] = value;
            }
            return r;
        }, undefined);

    if (temp) {
        Object.keys(o).forEach(function (k) {
            if (!(k in temp)) {
                temp[k] = o[k];
            }
        });
    }
    return temp;
}

function iterA(r, a) {
    var value = getValue(a);
    if (value) {
        r = r || [];
        r.push(value);
    }
    return r;
}

var data = [{ booking_name: "gtec/1101822/lmikdy/ls-rmea/oss11", asset_count: 2, pdg: "Invalid", user_area: "Invalid", deployment_number: "Invalid", spoc: "invalid", release: "Invalid", start_date: "2017-06-12 00:00:00", end_date: "2017-06-16 00:00:00", asset_info: [{ bams_id: "BAMS-1001423507", hostname: "GTVOSS11", status: 10, site_location: "IEAT01 Tipperary", rack_number: "VIRTUAL RACK", rack_u_position: 0, manufacturer: "EMC", model: "VM" }, { bams_id: "BAMS-1001368001", hostname: "None", status: 10, site_location: "IEAT01 Tipperary", rack_number: "VIRTUAL RACK", rack_u_position: 0, manufacturer: "HP", model: "HP BL460C GEN8" }], full_name: "Invalid (invalid)", email_address: "Invalid" }, { booking_name: "gtec/1101822/lmikdy/ls-rmea/oss11", asset_count: 2, pdg: "Invalid", user_area: "Invalid", deployment_number: "Invalid", spoc: "invalid", release: "Invalid", start_date: "2017-06-12 00:00:00", end_date: "2017-06-16 00:00:00", asset_info: [{ bams_id: "BAMS-1001423507", hostname: "GTVOSS11", status: 10, site_location: "IEAT01 Tipperary", rack_number: "VIRTUAL RACK", rack_u_position: 0, manufacturer: "EMC", model: "VM" }], full_name: "Invalid (invalid)", email_address: "Invalid" }],
    search = 'emc',
    result = data.reduce(iterA, undefined);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 134
Nina Scholz Avatar answered Feb 17 '26 18:02

Nina Scholz


I am unsure how deep your approach need to go, but this should do the trick

it will make a copy of each row when the child item has it, and replace the set with the matching values only

function filterSet(dataSet, matchFn) {
  return dataSet.reduce((current, row) => {
    if (typeof row === 'object') {
      for (let prop in row) {
        if (Array.isArray(row[prop])) {
          var set = filterSet(row[prop], matchFn);
          if (set && set.length > 0) {
            // copy the row, replace the array property with the results
            current.push( Object.assign({}, row,
              { [prop]: set }
            ) );
            // since the full row is now in there
            // no need to check more
            break;
          }
        } else if (matchFn(row[prop])) {
            // copy not ref
            current.push( Object.assign( {}, row ) );
            break;
          }
      }
    }
    return current;
  }, []);
}

var data = [{
    'booking_name': 'gtec/1101822/lmikdy/ls-rmea/oss11',
    'asset_count': 2,
    'pdg': 'Invalid',
    'user_area': 'Invalid',
    'deployment_number': 'Invalid',
    'spoc': 'invalid',
    'release': 'Invalid',
    'start_date': '2017-06-12 00:00:00',
    'end_date': '2017-06-16 00:00:00',
    'asset_info': [{
        'bams_id': 'BAMS-1001423507',
        'hostname': 'GTVOSS11',
        'status': 10,
        'site_location': 'IEAT01 Tipperary',
        'rack_number': 'VIRTUAL RACK',
        'rack_u_position': 0,
        'manufacturer': 'EMC',
        'model': 'VM',

      },
      {
        'bams_id': 'BAMS-1001368001',
        'hostname': 'None',
        'status': 10,
        'site_location': 'IEAT01 Tipperary',
        'rack_number': 'VIRTUAL RACK',
        'rack_u_position': 0,
        'manufacturer': 'HP',
        'model': 'HP BL460C GEN8',

      }
    ],
    'full_name': 'Invalid (invalid)',
    'email_address': 'Invalid'
  },
  {
    'booking_name': 'gtec/1101822/lmikdy/ls-rmea/oss11',
    'asset_count': 2,
    'pdg': 'Invalid',
    'user_area': 'Invalid',
    'deployment_number': 'Invalid',
    'spoc': 'invalid',
    'release': 'Invalid',
    'start_date': '2017-06-12 00:00:00',
    'end_date': '2017-06-16 00:00:00',
    'asset_info': [{
      'bams_id': 'BAMS-1001423507',
      'hostname': 'GTVOSS11',
      'status': 10,
      'site_location': 'IEAT01 Tipperary',
      'rack_number': 'VIRTUAL RACK',
      'rack_u_position': 0,
      'manufacturer': 'EMC',
      'model': 'VM',

    }],
    'full_name': 'Invalid (invalid)',
    'email_address': 'Invalid'
  }
];

console.log(filterSet(data, (i) => {
  return i.toString().toLowerCase().indexOf('emc') >= 0;
}));

console.log(filterSet(data, (i) => {
  return i.toString().toLowerCase().indexOf('invalid') >= 0;
}));
like image 28
Icepickle Avatar answered Feb 17 '26 18:02

Icepickle



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!