1

I want to filter the following object array based on max or min values of sales attribute.

data = [
  { region: 'Central', state: 'North Dakota', sales: 920 },
  { region: 'Central', state: 'South Dakota', sales: 1317 },
  { region: 'East', state: 'West Virginia', sales: 1209 },
  { region: 'East', state: 'Maine', sales: 1270 },
  { region: 'South', state: 'South Carolina', sales: 8483 },
  { region: 'South', state: 'Louisiana', sales: 9219 },
  { region: 'West', state: 'Wyoming', sales: 1603 },
  { region: 'West', state: 'Idaho', sales: 4380 },
  { region: 'West', state: 'California', sales: 4571 }
];

Filter the array based the maximum and minimum value of sales attribute. I'm looking for the following result:

newData = [
  { region: 'Central', min: 'North Dakota', max: 'South Dakota' },
  { region: 'East', min: 'West Virginia', max: 'Maine' },
  { region: 'South', min: 'South Carolina', max: 'Louisiana' },
  { region: 'West', min: 'Wyoming', max: 'California' }
];

Thanks in advance.

1
  • 2
    Welcome to SO! What did you try so far? Commented Aug 19, 2020 at 6:37

5 Answers 5

3

Ciao, you could try to filter data for region, then calculate max and min and push found object in result array like this:

let data = [
  { region: 'Central', state: 'North Dakota', sales: 920 },
  { region: 'Central', state: 'South Dakota', sales: 1317 },
  { region: 'East', state: 'West Virginia', sales: 1209 },
  { region: 'East', state: 'Maine', sales: 1270 },
  { region: 'South', state: 'South Carolina', sales: 8483 },
  { region: 'South', state: 'Louisiana', sales: 9219 },
  { region: 'West', state: 'Wyoming', sales: 1603 },
  { region: 'West', state: 'Idaho', sales: 4380 },
  { region: 'West', state: 'California', sales: 4571 }
];

let regions = ['Central', 'East', 'South', 'West'];

let result = [];

regions.forEach(region => {
   let dataFilter = data.filter(el => el.region === region);
   let max = Math.max(...dataFilter.map(el => el.sales));
   let min = Math.min(...dataFilter.map(el => el.sales));
   let dataMax = dataFilter.filter(el => el.sales === max )[0];
   let dataMin = dataFilter.filter(el => el.sales === min )[0];
   let objresult = {region: region, min: dataMin.state, max: dataMax.state};
   result.push(objresult);
})

console.log(result)

This is the version with dynamic regions:

let data = [
      { region: 'Central', state: 'North Dakota', sales: 920 },
      { region: 'Central', state: 'South Dakota', sales: 1317 },
      { region: 'East', state: 'West Virginia', sales: 1209 },
      { region: 'East', state: 'Maine', sales: 1270 },
      { region: 'South', state: 'South Carolina', sales: 8483 },
      { region: 'South', state: 'Louisiana', sales: 9219 },
      { region: 'West', state: 'Wyoming', sales: 1603 },
      { region: 'West', state: 'Idaho', sales: 4380 },
      { region: 'West', state: 'California', sales: 4571 }
    ];

    let regions = new Set(data.map(el => el.region));

    let result = [];

    regions.forEach(region => {
       let dataFilter = data.filter(el => el.region === region);
       let max = Math.max(...dataFilter.map(el => el.sales));
       let min = Math.min(...dataFilter.map(el => el.sales));
       let dataMax = dataFilter.filter(el => el.sales === max )[0];
       let dataMin = dataFilter.filter(el => el.sales === min )[0];
       let objresult = {region: region, min: dataMin.state, max: dataMax.state};
       result.push(objresult);
    })

    console.log(result)

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

4 Comments

@NinaScholz When I see your solutions I always think: why I didn't thought about that? But then I read better your code and I start to think another thing: why I don't understand what she wrote? :) Anyway I want to say that on algorithms you are excellent (and it's not the first time I thuoght that)
why not ask, what you don't understand?
@NinaScholz Today I understood what you have done (took 10 minutes to understand but I got it :)). But I promise that next time I don't understand some I will ask you. Anyway also today... a reducer with a map... how did you thought that? You made an intermediate solution and then optimize or you wrote just like that?
it just to have a look to the problem, the first is to group by region, which is the best (fatsest) to use an O(1) access, supplied by an object or Map. the second is to keep the min and max values. the second step is only to change the appearance of the result.
2

You could group by state and get min and max states.

This approach takes a single loop for gathering the data.

const
    data = [{ region: 'Central', state: 'North Dakota', sales: 920 }, { region: 'Central', state: 'South Dakota', sales: 1317 }, { region: 'East', state: 'West Virginia', sales: 1209 }, { region: 'East', state: 'Maine', sales: 1270 }, { region: 'South', state: 'South Carolina', sales: 8483 }, { region: 'South', state: 'Louisiana', sales: 9219 }, { region: 'West', state: 'Wyoming', sales: 1603 }, { region: 'West', state: 'Idaho', sales: 4380 }, { region: 'West', state: 'California', sales: 4571 }],
    result = Object
        .entries(data.reduce((r, { region, state, sales }) => {
            if (!r[region]) {
                r[region] = { min: { state, sales }, max: { state, sales } };
            } else if (r[region].min.sales > sales) {
                r[region].min.sales = sales;
                r[region].min.state = state;        
            } else if (r[region].max.sales < sales) {
                r[region].max.sales = sales;
                r[region].max.state = state;        
            }
            return r;
        }, {}))
        .map(([region, { min: { state: min }, max: { state: max } }]) => ({ region, min, max }));

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

Comments

1

You can use reduce and create an object with region as code. Then add value to that key and while adding check for the max and min with respective to current object. In the sales is greater or lesser than than max and min value , then replace the object data

data = [{
    region: 'Central',
    state: 'North Dakota',
    sales: 920
  },
  {
    region: 'Central',
    state: 'South Dakota',
    sales: 1317
  },
  {
    region: 'East',
    state: 'West Virginia',
    sales: 1209
  },
  {
    region: 'East',
    state: 'Maine',
    sales: 1270
  },
  {
    region: 'South',
    state: 'South Carolina',
    sales: 8483
  },
  {
    region: 'South',
    state: 'Louisiana',
    sales: 9219
  },
  {
    region: 'West',
    state: 'Wyoming',
    sales: 1603
  },
  {
    region: 'West',
    state: 'Idaho',
    sales: 4380
  },
  {
    region: 'West',
    state: 'California',
    sales: 4571
  }
];
let newData = data.reduce((acc, curr) => {
  // check if in accumulator object have a key same as region code.
  if (!acc[curr.region]) {
    // create a key and add value ,maxVal and minVal will be used to compare sales
    acc[curr.region] = {
      region: curr.region,
      min: curr.state,
      max: curr.state,
      maxVal: curr.sales,
      minVal: curr.sales
    }
  }
  if (curr.sales > acc[curr.region].maxVal) {
    acc[curr.region].max = curr.state;
    acc[curr.region].maxVal = curr.sales;
  }

  if (curr.sales < acc[curr.region].minVal) {
    acc[curr.region].min = curr.state;
    acc[curr.region].minVal = curr.sales;
  }
  return acc;
}, {})

console.log(Object.values(newData))

Comments

0
newData = [];

for(let i=0; i<data.length; i++){
  const matchedRegion = newData.findIndex((e) => e.region === data[i].region);
  if(matchedRegion !== -1){
    const min = data.find((f) => f.state === newData[matchedRegion].min).sales;
    const max = data.find((f) => f.state === newData[matchedRegion].max).sales;
    if(data[i].sales < min){
      newData[matchedRegion].min = data[i].state;
    } else if(data[i].sales > max){
      newData[matchedRegion].max = data[i].state;
    }
  } else {
    newData.push({region: data[i].region, min: data[i].state, max: data[i].state});
  }
}

Comments

0

Here's a nasty oneliner-esque you can use:

let data = [
  { region: 'Central', state: 'North Dakota', sales: 920 },
  { region: 'Central', state: 'South Dakota', sales: 1317 },
  { region: 'East', state: 'West Virginia', sales: 1209 },
  { region: 'East', state: 'Maine', sales: 1270 },
  { region: 'South', state: 'South Carolina', sales: 8483 },
  { region: 'South', state: 'Louisiana', sales: 9219 },
  { region: 'West', state: 'Wyoming', sales: 1603 },
  { region: 'West', state: 'Idaho', sales: 4380 },
  { region: 'West', state: 'California', sales: 4571 }
];

let newData = Array.from(new Set(data.map((item) => item.region)))
.map((region) => ({
    region: region,
    min: data.filter((item) => item.region == region).reduce((acc, cur) => cur.sales < acc.sales ? cur : acc, {sales: Infinity}).state,
    max: data.filter((item) => item.region == region).reduce((acc, cur) => cur.sales > acc.sales ? cur : acc, {sales: -Infinity}).state
}));

console.log(newData);

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.