0

I have an array of objects as below:

var arr =[
 {
  price:20,
  rule:a
 },
 {
  price:10,
  rule:b
 },
 {
  price:5,
  rule:a
 },
 {
  price:50,
  rule:b
 },
 {
  price:70,
  rule:b
 }
]

I want to extract an array of objects out of this as below:

var filteredArr = [
 {
  rule:a,
  countOfRule:2,
  minPriceForThisRule:5
 },
 {
  rule:b,
  countOfRule:3,
  minPriceForThisRule:10
 }
]

This means:

1) I want to create new array with no. of objects as unique no. of rules in first array "arr"

2) Need to count the unique rule repetition and add as property in new array objects - given as "countOfRule"

3) Find the minimum price for in a category of unique rule - given as "minPriceForThisRule"

I have read similar answers on SO and was able to get first 2 conditions only, and that too were not in the format as i need.

What I tried, referring to links on SO:

var ff = {},e;
for (var i = 0,l=arr.length; i < l; i++) {
   e = arr[i];
   ff[e.rule] = (ff[e.rule] || 0) + 1;
}

But this gives only a single object as

{
 a : 2,
 b: 3
}
3
  • 2
    Show us what you've done! Commented Jun 14, 2016 at 12:34
  • @NafiulIslam - Updated, what i tried. Commented Jun 14, 2016 at 12:38
  • @mplungjan - Sorry, I didn't get that. Could you please explain a little more. Commented Jun 14, 2016 at 12:40

3 Answers 3

2

You can do this with forEach and thisArg optional parameter.

var arr = [{"price":20,"rule":"a"},{"price":10,"rule":"b"},{"price":5,"rule":"a"},{"price":50,"rule":"b"},{"price":70,"rule":"b"}], 
    r = [];

arr.forEach(function(e) {
  if(!this[e.rule]) {
    this[e.rule] = {rule: e.rule, countOfRule: 0, minPriceForThisRule: e.price}
    r.push(this[e.rule]);
  }
  this[e.rule].countOfRule++;
  if(this[e.rule].minPriceForThisRule > e.price) this[e.rule].minPriceForThisRule = e.price;
}, {});

console.log(r)

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

6 Comments

Thanks, let me try this out.
Hey, just out of curiosity, how do you come up with such an answer and that too so fast. Building this logic and all. Would you have some recommendations for me on this, as to any javascript algo books, references etc. which could help me in such cases.
its just a standard pattern, which is not completely copied.
I learned to solve problems like this from smarter and more experienced developers then me here on SO, but some good places to learn also are eloquentjavascript.net, developer.mozilla.org/en-US/docs/Web/JavaScript
Thanks again for the references. And yes, am also doing same, as far as SO goes :-)
|
0

I would use reduce. Something like:

var reduced = arr.reduce(function(memo, obj){
   var rule = memo[obj.rule];
   rule.countOfRule++;
   if(!rule.minPriceForThisRule){
     rule.minPriceForThisRule = obj.price;
   } else{
     if(obj.price < rule.minPriceForThisRule){
       rule.minPriceForThisRule = obj.price;
     }
   }
   return memo;
}, map);

where the initial map looks like:

var map = {
  1: {
    rule: 1,
    countOfRule: 0,
    minPriceForThisRule: null      
  },
  2: {
    rule: 2,
    countOfRule: 0,
    minPriceForThisRule: null        
  }
}

Of course you could dynamically create the map if needed.

https://plnkr.co/edit/wLw3tEx2SMXmYE7yOEHg?p=preview

Comments

0

This is how i would do this job,

var arr =[
 {
  price:20,
  rule:"a"
 },
 {
  price:10,
  rule:"b"
 },
 {
  price:5,
  rule:"a"
 },
 {
  price:50,
  rule:"b"
 },
 {
  price:70,
  rule:"b"
 }
],
reduced = arr.reduce((p,c) => { var fo = p.find(f => f.rule == c.rule);
                                fo ? (fo.countOfRule++,
                                      fo.minPriceForThisRule > c.price && (fo.minPriceForThisRule = c.price))
                                   :  p.push({rule:c.rule, countOfRule:1, minPriceForThisRule: c.price});
                                return p;
                              },[]);
console.log(reduced);

Arrows might not work at IE or Safari. If that would be a problem please replace them with their conventional counterparts.

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.