0

I have an array of objects as below. I want to sort the array with categories and also find the number of total item in each category. As in below example all category with "toys" should come one after other and it should also be easy to get the count like in below example it is 2(for toys category).

[
 { "category": "toys", "name": "cycle", "itemID": 1594, "price": 1594},
 { "category": "furniture", "name": "chair", "itemID": 15954, "price": 1594},},
 { "category": "furniture", "name": "table", "itemID": 15344, "price": 1594},},
 { "category": "books", "name": "twoLittle", "itemID": 153594, "price": 1594},},
 { "category": "electronic", "name": "Tape", "itemID": 134594, "price": 1594},},
 { "category": "books", "name": "oneLittle", "itemID": 1594436, "price": 1594},},
 { "category": "electronic", "name": "TV", "itemID": 159446, "price": 1594},
 { "category": "toys", "name": "car", "itemID": 1534694, "price": 1594},
]

Any help in right direction would be highly appreciated.

Thanks in advance.

Ekra
  • 3,241
  • 10
  • 41
  • 61
  • 1
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort – Kevin Boucher Nov 06 '17 at 17:46
  • 3
    Possible duplicate of [Sort array of objects by string property value in JavaScript](https://stackoverflow.com/questions/1129216/sort-array-of-objects-by-string-property-value-in-javascript) – Kevin Boucher Nov 06 '17 at 17:46

4 Answers4

1

You can use custom sort method using localeCompare. You can use array#reduce to get count of each category.

const data = [{ "category": "toys", "name": "cycle", "itemID": 1594},{ "category": "furniture", "name": "chair", "itemID": 15954},{ "category": "furniture", "name": "table", "itemID": 15344},{ "category": "books", "name": "twoLittle", "itemID": 153594},{ "category": "electronic", "name": "Tape", "itemID": 134594},{ "category": "books", "name": "oneLittle", "itemID": 1594436},{ "category": "electronic", "name": "TV", "itemID": 159446},{ "category": "toys", "name": "car", "itemID": 1534694}];

data.sort((a,b) => a.category.localeCompare(b.category));
console.log(data);

var distinctCount = data.reduce((r,{category}) => {
  r[category] = (r[category] || 0) + 1;
  return r;
},{})

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

ES 5 Code:

var data = [{ "category": "toys", "name": "cycle", "itemID": 1594 }, { "category": "furniture", "name": "chair", "itemID": 15954 }, { "category": "furniture", "name": "table", "itemID": 15344 }, { "category": "books", "name": "twoLittle", "itemID": 153594 }, { "category": "electronic", "name": "Tape", "itemID": 134594 }, { "category": "books", "name": "oneLittle", "itemID": 1594436 }, { "category": "electronic", "name": "TV", "itemID": 159446 }, { "category": "toys", "name": "car", "itemID": 1534694 }];

data.sort(function (a, b) {
  return a.category.localeCompare(b.category);
});
console.log(data);

var distinctCount = data.reduce(function (r, obj) {
  var category = obj.category;
  r[category] = (r[category] || 0) + 1;
  return r;
}, {});

console.log(distinctCount);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
  • the ES6 arrow functions is not compiling for me can you update the answer with old ES5 method of function – Ekra Nov 06 '17 at 18:46
  • the code works perfect but I have a query as to how to get the values inside distinctCount as we don't know the runtime keys inside it (like toys, furniture). Note console.log doesn't work at my application. Basically i cannot use distinctCount.catergoryName – Ekra Nov 06 '17 at 19:40
  • Basically, `distinctCount` is a normal Javascript object. To access all the keys inside `distinctCount` you can use [`Object.keys()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys), it will give you an array of keys, using which you can iterate through all keys inside `distinctCount`. – Hassan Imam Nov 07 '17 at 02:55
1

It sounds like what you actually want to do is create an object with the category as the key:

var categories = items.reduce(function(acc, item) {
    if (typeof acc[item.category] === 'undefined') {
        acc[item.category] = [];
    }
    acc[item.category].push(item);
    return acc;
}, {});

And now you can do:

   var num_toys = categories.toys.length; //2

Or if you want to iterate over the toys:

categories.toys.forEach(function(toy) {
    console.log(toy.name);
});

Then, you effectively get "sorting" for free (they are grouped by category), you can easily get the number of items in each category (you just check the .length of the item).

var items = [
 { "category": "toys", "name": "cycle", "itemID": 1594},
 { "category": "furniture", "name": "chair", "itemID": 15954},
 { "category": "furniture", "name": "table", "itemID": 15344},
 { "category": "books", "name": "twoLittle", "itemID": 153594},
 { "category": "electronic", "name": "Tape", "itemID": 134594},
 { "category": "books", "name": "oneLittle", "itemID": 1594436},
 { "category": "electronic", "name": "TV", "itemID": 159446},
 { "category": "toys", "name": "car", "itemID": 1534694}
]

var categories = items.reduce(function(acc, item) {
    if (typeof acc[item.category] === 'undefined') {
        acc[item.category] = [];
    }
    acc[item.category].push(item);
    return acc;
}, {});

console.log(categories, categories.toys.length);
dave
  • 62,300
  • 5
  • 72
  • 93
  • I cannot hard code the category name it can be anything at runtime – Ekra Nov 06 '17 at 18:18
  • then you can do `categories[category_name].length` – dave Nov 06 '17 at 18:19
  • it would be great if u could elaborate what you mean by category_name. OR you can update the answer thanks @dave – Ekra Nov 06 '17 at 18:31
  • `var category_name = 'toys'; categories[category_name].length` - you can set `category_name` dynamically, it doesn't have to be hardcoded. – dave Nov 06 '17 at 18:33
1

one liner code and simplest one for you

     data = [
     { "category": "toys", "name": "cycle", "itemID": 1594},
     { "category": "furniture", "name": "chair", "itemID": 15954},
     { "category": "furniture", "name": "table", "itemID": 15344},
     { "category": "books", "name": "twoLittle", "itemID": 153594},
     { "category": "electronic", "name": "Tape", "itemID": 134594},
     { "category": "books", "name": "oneLittle", "itemID": 1594436},
     { "category": "electronic", "name": "TV", "itemID": 159446},
     { "category": "toys", "name": "car", "itemID": 1534694}
    ]

    data.sort(function(a, b) {
        return (a.category)<(b.category);
    });

    count = function (ary, classifier) {
    classifier = classifier || String;
    return ary.reduce(function (counter, item) {
        var p = classifier(item);
        counter[p] = counter.hasOwnProperty(p) ? counter[p] + 1 : 1;
        return counter;
    }, {})
};
countByCategory = count(data, function (item) {
    return item.category
});
Argus Malware
  • 773
  • 7
  • 19
1

I have broken it down into simple steps.

  1. count the totals this can be factored to do averages etc later
  2. Pass the objects into an array (1 for each cat)
  3. Sort the array on the property of choice (count, name or cat)

The end result is an array of the objects including a count property assuming this may need to be used for rendering / templating.

https://jsfiddle.net/wj9m7yz1/

 var data = [
     { "category": "toys", "name": "cycle", "itemID": 1594},
     { "category": "furniture", "name": "chair", "itemID": 15954},
     { "category": "furniture", "name": "table", "itemID": 15344},
     { "category": "books", "name": "twoLittle", "itemID": 153594},
     { "category": "electronic", "name": "Tape", "itemID": 134594},
     { "category": "books", "name": "oneLittle", "itemID": 1594436},
     { "category": "electronic", "name": "TV", "itemID": 159446},
     { "category": "toys", "name": "car", "itemID": 1534694}
    ];
    var result={},arr=[], sorted;
    // count the totals and keep all your initial data!
    for (var i = data.length - 1; i >= 0; i--) {
        var item = data[i],
              cat = item.category;
         result[cat] = result[cat] || {name:item.name, category: cat, count:0};
         result[cat].count ++; 

    }
    // pass to an array for sort
    for (var o in result){arr.push(result[o])};
    // sort on desired prop - in this case count
    sorted =  arr.sort(function(a,b) {return (a.count > b.count) ? 1 : ((b.count > a.count) ? -1 : 0);} ); 
    console.log(sorted)
MartinWebb
  • 1,998
  • 1
  • 13
  • 15