1

I have an array of objects like this

const myArr = [
  {
    gender: 'female', items: 25, price: 250
  },
  {
    gender: 'male', items: 28, price: 112
  },
  {
    gender: 'unknown', items: 22, price: 82
  },
  {
    gender: 'Unknown', items: 23, price: 7
  },
  {
    gender: '', items: 27, price: 200
  }
];

and I want to group objects by gender if the gender value is 'unknown', 'Unknown' or an empty string, and sum the other values so the result will be like this:

const myArr = [
  {
    gender: 'female', items: 25, price: 250
  },
  {
    gender: 'male', items: 28, price: 112
  },
  {
    gender: 'unknown', items: 72, price: 289
  },
];

What I've tried is to check if the gender is 'unknown', 'Unknown' or an empty string and group them to 'unknown' if true, but what I'm not sure is how to sum the values of items and price. Here is the code of what I've tried:

const myNewArr = Object.values(
  myArr.reduce(function (r, { gender, items, price }) {
     if (gender === 'unknown' || gender === 'Unknown' || gender === '') {
       gender = 'unknown';
       r[items] = r[items] + items;
       r[price] = r[price] + price; // here i need to sum items and price somehow
     }
     r[gender] = r[gender] || { gender, items, price};
     r[gender].items = r[items];
     r[gender].price = r[price];
     return r;
  }, Object.create(null))
);

What am I doing wrong? Any example would be appreciated!

2
  • The expected result is wrong. For gender 'unknown' items count should be '72'. Commented Nov 17, 2020 at 17:18
  • Thanks for your review, I've changed it to 72 Commented Nov 17, 2020 at 17:19

2 Answers 2

2

You need to normalize gender to lower case or take unknown.

Then you need to add the values to each related property.

const
    array = [{ gender: 'female', items: 25, price: 250 }, { gender: 'male', items: 28, price: 112 }, { gender: 'unknown', items: 22, price: 82 }, { gender: 'Unknown', items: 23, price: 7 }, { gender: '', items: 27, price: 200 }],
    result = Object.values(array.reduce(function (r, { gender, items, price }) {
        gender = gender.toLowerCase() || 'unknown';
        if (r[gender]) {
            r[gender].items += items;
            r[gender].price += price;
        } else {
            r[gender] = { gender, items, price };
        }
        return r;
    }, Object.create(null)));

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

Sign up to request clarification or add additional context in comments.

Comments

1

You need to check if the values already exist on the accumulator and return a different result depending on if they're there or not. I'm using the spread syntax to create a new object on each iteration.

Also, you should avoid reassigning paramters as you've done here:

gender = 'unknown';

Below is a working version of the code

const myArr = [
  {
    gender: "female",
    items: 25,
    price: 250,
  },
  {
    gender: "male",
    items: 28,
    price: 112,
  },
  {
    gender: "unknown",
    items: 22,
    price: 82,
  },
  {
    gender: "Unknown",
    items: 23,
    price: 7,
  },
  {
    gender: "",
    items: 27,
    price: 200,
  },
]

const myNewArr = myArr.reduce((accumulator, { gender, items, price }) => {
  if (gender.toLowerCase() === "unknown" || !gender) {
    if (!accumulator.hasOwnProperty("unknown")) {
      return { ...accumulator, unknown: { items, price } }
    } else {
      return {
        ...accumulator,
        unknown: {
          ...accumulator.unknown,
          price: price + accumulator.unknown.price,
          items: items + accumulator.unknown.items,
        },
      }
    }
  } else {
    if (!accumulator.hasOwnProperty(gender)) {
      return { ...accumulator, [gender]: { price, items } }
    }
    return {
      ...accumulator,
      [gender]: {
        price: price + accumulator[gender].price,
        items: items + accumulator[gender].items,
      },
    }
  }
}, {})

console.log(myNewArr)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.