Ekra
Ekra

Reputation: 3301

Sorting of array objects in javascript

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.

Upvotes: 0

Views: 113

Answers (4)

Hassan Imam
Hassan Imam

Reputation: 22574

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; }

Upvotes: 1

MartinWebb
MartinWebb

Reputation: 2008

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)

Upvotes: 1

Argus Malware
Argus Malware

Reputation: 787

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
});

Upvotes: 1

dave
dave

Reputation: 64695

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);

Upvotes: 1

Related Questions