1

I'm trying to categorize an array of questions I've gotten from our application's API, and I've come up with a method that works, but it doesn't feel awesome. Can anyone tell me if there's a better way to do this?

Here's the code I have now. I'm not too worried about making it super optimized, but it shouldn't end up slow.

$scope.patron.categories = questions.map(function(question, i) {
    // check if question has a new CategoryId
    if(i === 0 || (i > 0 && question.CategoryId !== questions[i-1].CategoryId)) {
        // put questions with the same CategoryId together
        var catQuestions = questions.filter(function(q) {
            return q.CategoryId === question.CategoryId;
        });

        return {
            id: question.CategoryId,
            name: question.Category,
            collapsed: true,
            valid: false,
            questions: catQuestions
        };
    }
}).filter(function(category) {
    // because Array.prototype.map doesn't remove these by itself
    return category !== undefined;
});
2
  • 2
    codereview.stackexchange.com Commented Oct 5, 2015 at 21:15
  • You can use a Set to efficiently store the set of unique values used to distinguish elements. As you'd expect, Set.add() will silently not create duplicate entries, and Set.has() scales better than Array.indexOf() Commented Oct 5, 2015 at 21:42

1 Answer 1

1

Although it's primarily opinion-based, I prefer a simple loop.

For sure it's better for performance, and I think it's better for readability also.

var catIds = [], cats = [];

questions.forEach(function(q, i) {
  var idx = catIds.indexOf(q.CategoryId);
  if (idx === -1) {
    catIds.push(q.CategoryId);
    cats.push({
      id: q.CategoryId,
      name: q.Category,
      collapsed: true,
      valid: false,
      questions: [q]
    });
  }
  else {
    cats[idx].questions.push(q);
  }
});

$scope.patron.categories = cats;
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, this is great, and pretty clean, too.

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.