1

Working on a font library, I store fonts like this:

var fonts = [
    {
        name: "Foo",
        style: "Bar",
        families: [
            { name: "A", parent: "B" },
            { name: "C", parent: "D" }
        ]
    } // and so on...
];

And I want to filter out fonts whose families list contains { name: "A", parent: "B" }.

The filter looks like var selection = [{ name: "A", parent: "B" }]

Actually, the code look like this:

// Triggers when a new family is added to the filter
$scope.$on('filter:changed', function(e, selection) {

    _.each($scope.fonts, function(font) {

        _.each(font.families, function(family) {

            _.each(selection, function(item) {

                if(_.isMatch(family, item)) {
                    console.log('font', font);
                    console.log('has a match for family', family);
                } else {
                    console.log('no match for family', family);
                }
            });
        });
    });
});

What is the best way to do it without performance impact, as there will be thousands font objects in the future?

3
  • Since you're using underscore. You could look @ findWhere or where Commented May 7, 2015 at 16:22
  • @dcodesmith is right, use where to get the array or findWhere if you want only one result Commented May 7, 2015 at 16:30
  • Thanks for your answers. The selection might not be a single object as in the example, but an array of objects. I think I should iterate over $scope.fonts, then over the selectors (selection array) and test them with _.where, right? Commented May 11, 2015 at 7:42

2 Answers 2

1

underscore#where

$scope.$on('filter:changed', function(e, selection) {
    var multiselection,
        singleSelection;
    _.each($scope.fonts, function(font) {
        multiselection = _.where(font.families, { name: "A", parent: "B" }); //all matching objects
        singleSelection = _.findWhere(font.families, { name: "A", parent: "B" }); // single matching object
    });
});

JSFIDDLE

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

Comments

0

Since you're using underscore use filter

From underscore docs:

_.filter(list, predicate, [context]) Alias: select Looks through each value in the list, returning an array of all the values that pass a truth test (predicate).

So your filter would be (use this only if you want to manipulate data for each object, otherwise use where):

var myFamilyMatch = { name: "A", parent: "B" };

var selection = _.filter(fonts, function(font){
  return _find(font.families, function(family){
     return family == myFamilyMatch;
  };
});

Or simply (and better) use where as @dcodesmith suggested:

_.where(list, properties) Looks through each value in the list, returning an array of all the values that contain all of the key-value pairs listed in properties.

Underscore will take care of performance for you, so don't worry about it.

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.