Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

185
Views
How to reduce a property within an array of array?

I have an array of products which in turn have an array of categories. I want to extract distinct values of the type property on category object.
Both the Lodash and native versions below do the job.
I want to make a generic function which takes the path of property and return unique values.

Essentially I am looking at something terse like map(products, property("categories[].type") but heres the longer version(s)

import { compact, flatten, map, property, uniq } from "lodash";

export const getAllTypes1 = (products) => {
  return uniq(
    compact(map(flatten(map(products, property("categories"))), "type"))
  );
};
export const getAllTypes2 = (products) => {
  const types = [];
  products.forEach((product) => {
    product.categories.forEach((category) => {
      if (!types.some((t) => t === category.type)) {
        types.push(category.type);
      }
    });
  });
  return types;
};

Example data

const product1 = {
  name: 'Wilson Orange',
  price: 72.50,
  categories: [{
    type: 'flash sale',
    discountable: false,
  },{
    type: 'tennis',
    discountable: true,
  }]
};
const product2 = {
  name: 'Babolat Green',
  price: 65.50,
  categories: [{
    type: 'tennis',
    discountable: true,
  }]
};
const products = [product1, product2];

Result

const result = getAllTypes2(products);
console.log(result); // ["flash sale", "tennis"]

Here's a working example

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Here's a vanilla JS function that takes the path without needing [] and automatically checks arrays wherever it finds one.

How it works is:

  1. Create an empty Set to easily remove duplicates
  2. Turn the path string to an array of properties -> props
  3. Call a recursive function recurse(currObj, props) which:
    1. Checks if the currObj is an array, and if it is: a. Recurses again with the array values as currObj b. Use the same props since we didn't check an object in the path
    2. Check if we're at the last prop in the path, if yes a. Add the property's value in the current object to the set
    3. Otherwise. recurse with currObj[currProp], and the remaining props
  4. Convert the set to an array and return it.

const product1 = {
  name: 'Wilson Orange',
  price: 72.5,
  categories: [
    {
      type: 'flash sale',
      discountable: false,
    },
    {
      type: 'tennis',
      discountable: true,
    },
  ],
};
const product2 = {
  name: 'Babolat Green',
  price: 65.5,
  categories: [
    {
      type: 'tennis',
      discountable: true,
    },
  ],
};
const products = [product1, product2];

function getProperties(array, path) {
  const props = path.split('.');
  const values = new Set();

  function recurse(currObj, props) {
    const currProp = props[0]
    const nextProps = props.slice(1);
    if (Array.isArray(currObj)) {
      for (let val of currObj) {
        recurse(val, props);
      }
      return
    }
    if (nextProps.length === 0) {
      values.add(currObj[currProp])
    } else {
      recurse(currObj[currProp], nextProps)
    } 
  }
  recurse(array, props);
  return [...values];
}

console.log(getProperties(products,'categories.type'))
console.log(getProperties(products,'price'))
console.log(getProperties(products,'name'))

about 4 years ago · Juan Pablo Isaza Report

0

It's not a property path string, but it's pretty terse and expressive:

const pipe = (...fs) => fs.reduceRight(
  (next, f) => x => f(x, next), x => x,
);
const getAllTypes = pipe(
  (x, next) => [...new Set(x.flatMap(next))],
  (x, next) => x.categories.map(next),
  (x) => x.type,
);
// equivalent to
// const getAllTypes =
//   x => [...new Set(x.flatMap(y => y.categories.map(z => z.type)))];

const products = [{
  name: 'Wilson Orange',
  price: 72.50,
  categories: [{
    type: 'flash sale',
    discountable: false,
  }, {
    type: 'tennis',
    discountable: true,
  }]
}, {
  name: 'Babolat Green',
  price: 65.50,
  categories: [{
    type: 'tennis',
    discountable: true,
  }]
}];

console.log(getAllTypes(products));

The parameter x => x allows pipe to be called without any arguments and return the identity function. It also allows the last function argument of pipe to accept a next parameter for consistency, i.e. (x, next) => next(x.type) would have been equivalent to (x) => x.type.

Reference:

  • Array.prototype.flatMap
  • Array.prototype.map
  • Array.prototype.reduceRight
  • Set
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!