Plucking objects from multi-dimensional array

Viewed 133

Say we have the following array:

const admins = [
      {
        adminName: 'admin 1',
        devices: [
          {
            deviceName: 'device 1',
            os: 'desktop',
            appVersion: 1.2.0
          },
          {
            deviceName: 'device 2',
            os: 'desktop',
            appVersion: 1.4.0
          }
        ]
      },
      {
        adminName: 'admin 2',
        devices: [
          {
            deviceName: 'device 1',
            os: 'ios',
            appVersion: 1.4.0
          },
          {
            deviceName: 'device 2',
            os: 'android',
            appVersion: 1.1.0
          }
        ]
      }
    ]

I'm attempting to gather all the devices from various admins into a single array like so.

const adminDevices = admins.map(admin => admin.devices);

But this returns an array that has another array in it which contains the devices.

I have tried the following:

const adminDevices = admins.map((admin) => {
   return admin.devices.reduce((accumulator, value) => {
     return value;
   }, {});
});

But this as expected only returns the first device value. Any suggestions on how I could accomplish this with any of the Array methods without having to declare an empty array or set and fill that out manually?

2 Answers

Use .flatMap:

const admins = [
  {
    adminName: 'admin 1',
    devices: [
      { deviceName: 'device 1', os: 'desktop', appVersion: '1.2.0' },
      { deviceName: 'device 2', os: 'desktop', appVersion: '1.4.0' }
    ]
  },
  {
    adminName: 'admin 2',
    devices: [
      { deviceName: 'device 1', os: 'ios', appVersion: '1.4.0' },
      { deviceName: 'device 2', os: 'android', appVersion: '1.1.0' }
    ]
  }
];

const adminDevices = admins.flatMap(admin => admin.devices);

console.log(adminDevices)

If you are going to go ahead and flat-map the device lists, I would also try to associate the adminName to each device. This way you do not lose any info when ungrouping.

const admins = [{
  adminName: 'admin 1',
  devices: [
    { deviceName: 'device 1' , os: 'desktop' , appVersion: '1.2.0' },
    { deviceName: 'device 2' , os: 'desktop' , appVersion: '1.4.0' }
  ]
}, {
  adminName: 'admin 2',
  devices: [
    { deviceName: 'device 1' , os: 'ios'     , appVersion: '1.4.0' },
    { deviceName: 'device 2' , os: 'android' , appVersion: '1.1.0' }
  ]
}];

const adminDevices = admins.flatMap(({ adminName, devices }) =>
  devices.map((device) => ({ adminName, ...device })));

adminDevices.forEach(device => console.log(JSON.stringify(device)));
.as-console-wrapper { top: 0; max-height: 100% !important; }

Related