0

I have an array of items which are featured components like this:

var featuredIds = ['footerB', 'headerA', 'landingA'];

I also have an array of objects that looks something like this:

[{
    "title": "first footer",
    "section": "structure",
    "categoryId": "footer",
    "uId": "footerA"
  },{
    "title": "second footer",
    "section": "structure",
    "categoryId": "footer",
    "uId": "footerB"
  },
  {
    "title": "first header",
    "section": "structure",
    "categoryId": "header",
    "uId": "headerA"
  },
  {
    "title": "first header",
    "section": "structure",
    "categoryId": "header",
    "uId": "headerB"
  },
  {
    "title": "first landing",
    "section": "structure",
    "categoryId": "landing",
    "uId": "landingA"
  },
  {
    "title": "second landing",
    "section": "structure",
    "categoryId": "landing",
    "uId": "landingB"
  },
  {
    "title": "third landing",
    "section": "structure",
    "categoryId": "landing",
    "uId": "landingC"
  },
  {
    "title": "first nav",
    "section": "structure",
    "categoryId": "navigation",
    "uId": "navA"
  },{
    "title": "first footer",
    "section": "components",
    "categoryId": "blog",
      "uId": "blogA"
  },
  {
    "title": "second footer",
    "section": "components",
    "categoryId": "blog",
    "uId": "blogB"
  },
  {
    "title": "first header",
    "section": "components",
    "categoryId": "contact_button",
    "uId": "contact_buttonA"
  },
  {
    "title": "first landing",
    "section": "components",
    "categoryId": "content_bloc",
    "uId": "content_blocA"
  },
  {
    "title": "second landing",
    "section": "components",
    "categoryId": "content_bloc",
    "uId": "content_blocB"
  },
  {
    "title": "third landing",
    "section": "components",
    "categoryId": "content_bloc",
    "uId": "content_blocC"
  },
  {
    "title": "first nav",
    "section": "components",
    "categoryId": "cover",
    "uId": "coverA"
  }]

I want to create a new array which only holds the components that match the featureIds I provide in the array of featureIds which would look like this:

[{
    "title": "second footer",
    "section": "structure",
    "categoryId": "footer",
    "uId": "footerB"
  },{
    "title": "first header",
    "section": "structure",
    "categoryId": "header",
    "uId": "headerA"
  },
  {
    "title": "first landing",
    "section": "structure",
    "categoryId": "landing",
    "uId": "landingA"
  }]

I have looked at using _.some, _.find and a few others but haven't been able to get the result I am looking for. I have written this already using a double for loop which is why I want to us lodash to cut that out/learn something new.

2 Answers 2

2

You can use lodash's chain with _.keyBy() and _.at():

function filterBy(arr, filters) {
  return _(features)
  .keyBy('uId')
  .at(filters)
  .value();
}

var features = [{
  "title": "first footer",
  "section": "structure",
  "categoryId": "footer",
  "uId": "footerA"
}, {
  "title": "second footer",
  "section": "structure",
  "categoryId": "footer",
  "uId": "footerB"
}, {
  "title": "first header",
  "section": "structure",
  "categoryId": "header",
  "uId": "headerA"
}, {
  "title": "first header",
  "section": "structure",
  "categoryId": "header",
  "uId": "headerB"
}, {
  "title": "first landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingA"
}, {
  "title": "second landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingB"
}, {
  "title": "third landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingC"
}, {
  "title": "first nav",
  "section": "structure",
  "categoryId": "navigation",
  "uId": "navA"
}, {
  "title": "first footer",
  "section": "components",
  "categoryId": "blog",
  "uId": "blogA"
}, {
  "title": "second footer",
  "section": "components",
  "categoryId": "blog",
  "uId": "blogB"
}, {
  "title": "first header",
  "section": "components",
  "categoryId": "contact_button",
  "uId": "contact_buttonA"
}, {
  "title": "first landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocA"
}, {
  "title": "second landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocB"
}, {
  "title": "third landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocC"
}, {
  "title": "first nav",
  "section": "components",
  "categoryId": "cover",
  "uId": "coverA"
}];

var featuredIds = ['footerB', 'headerA', 'landingA'];

var result = filterBy(features, featuredIds);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.6/lodash.min.js"></script>

Or if you can use ES6, a combination of Array.prototype.filter() and Set:

const filterBy = (arr, filters) => {
  const filtersSet = new Set(filters);
  
  return arr.filter((item) => filtersSet.has(item.uId));
};

const featuredIds = ['footerB', 'headerA', 'landingA'];

const features = [{
  "title": "first footer",
  "section": "structure",
  "categoryId": "footer",
  "uId": "footerA"
}, {
  "title": "second footer",
  "section": "structure",
  "categoryId": "footer",
  "uId": "footerB"
}, {
  "title": "first header",
  "section": "structure",
  "categoryId": "header",
  "uId": "headerA"
}, {
  "title": "first header",
  "section": "structure",
  "categoryId": "header",
  "uId": "headerB"
}, {
  "title": "first landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingA"
}, {
  "title": "second landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingB"
}, {
  "title": "third landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingC"
}, {
  "title": "first nav",
  "section": "structure",
  "categoryId": "navigation",
  "uId": "navA"
}, {
  "title": "first footer",
  "section": "components",
  "categoryId": "blog",
  "uId": "blogA"
}, {
  "title": "second footer",
  "section": "components",
  "categoryId": "blog",
  "uId": "blogB"
}, {
  "title": "first header",
  "section": "components",
  "categoryId": "contact_button",
  "uId": "contact_buttonA"
}, {
  "title": "first landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocA"
}, {
  "title": "second landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocB"
}, {
  "title": "third landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocC"
}, {
  "title": "first nav",
  "section": "components",
  "categoryId": "cover",
  "uId": "coverA"
}];

const result = filterBy(features, featuredIds);

console.log(result);

Another lodash option is _.intersectionWith():

function filterBy(arr, filters) {
  return _.intersectionWith(arr, filters, function(value, filter) {
    return value.uId === filter;
  });
}

var features = [{
  "title": "first footer",
  "section": "structure",
  "categoryId": "footer",
  "uId": "footerA"
}, {
  "title": "second footer",
  "section": "structure",
  "categoryId": "footer",
  "uId": "footerB"
}, {
  "title": "first header",
  "section": "structure",
  "categoryId": "header",
  "uId": "headerA"
}, {
  "title": "first header",
  "section": "structure",
  "categoryId": "header",
  "uId": "headerB"
}, {
  "title": "first landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingA"
}, {
  "title": "second landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingB"
}, {
  "title": "third landing",
  "section": "structure",
  "categoryId": "landing",
  "uId": "landingC"
}, {
  "title": "first nav",
  "section": "structure",
  "categoryId": "navigation",
  "uId": "navA"
}, {
  "title": "first footer",
  "section": "components",
  "categoryId": "blog",
  "uId": "blogA"
}, {
  "title": "second footer",
  "section": "components",
  "categoryId": "blog",
  "uId": "blogB"
}, {
  "title": "first header",
  "section": "components",
  "categoryId": "contact_button",
  "uId": "contact_buttonA"
}, {
  "title": "first landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocA"
}, {
  "title": "second landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocB"
}, {
  "title": "third landing",
  "section": "components",
  "categoryId": "content_bloc",
  "uId": "content_blocC"
}, {
  "title": "first nav",
  "section": "components",
  "categoryId": "cover",
  "uId": "coverA"
}];

var featuredIds = ['footerB', 'headerA', 'landingA'];

var result = filterBy(features, featuredIds);

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.16.6/lodash.min.js"></script>

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

5 Comments

what is your opinion of the best function to use? _.intersectionBy or the current one in the answer? I am trying to work out the if typeof part as it seems strange to me as you return item as well. i guess its something under the hood in lodash that gets the right object
The _.keyBy method is more clean. The _.intersection() was an idea, but I've decided it's a bit hackish. Because we intersect the two arrays, an items can be a feature object or string, so I need to extract the value to intersect with.
Thank you for that and thank you for explaining. It didnt quite sit right with me and wasn't quite sure why but now you say its hackish, it makes sense.
Thanks. I've added another option using _.intersectionWith(), which is nicer then the one with the _.intersectionBy().
thanks for adding another option. I quite like intersectionWith(). it reads better than the key chaining one i feel
1

You can do this with filter() and includes() in plain js.

var data = [{"title":"first footer","section":"structure","categoryId":"footer","uId":"footerA"},{"title":"second footer","section":"structure","categoryId":"footer","uId":"footerB"},{"title":"first header","section":"structure","categoryId":"header","uId":"headerA"},{"title":"first header","section":"structure","categoryId":"header","uId":"headerB"},{"title":"first landing","section":"structure","categoryId":"landing","uId":"landingA"},{"title":"second landing","section":"structure","categoryId":"landing","uId":"landingB"},{"title":"third landing","section":"structure","categoryId":"landing","uId":"landingC"},{"title":"first nav","section":"structure","categoryId":"navigation","uId":"navA"},{"title":"first footer","section":"components","categoryId":"blog","uId":"blogA"},{"title":"second footer","section":"components","categoryId":"blog","uId":"blogB"},{"title":"first header","section":"components","categoryId":"contact_button","uId":"contact_buttonA"},{"title":"first landing","section":"components","categoryId":"content_bloc","uId":"content_blocA"},{"title":"second landing","section":"components","categoryId":"content_bloc","uId":"content_blocB"},{"title":"third landing","section":"components","categoryId":"content_bloc","uId":"content_blocC"},{"title":"first nav","section":"components","categoryId":"cover","uId":"coverA"}];
var featuredIds = ['footerB', 'headerA', 'landingA'];

var result = data.filter(function(e) {
  return featuredIds.includes(e.uId);
})

console.log(result)

2 Comments

Thank you! for your help
Note that includes() is ES6 you can also use indexOf() instead like this jsfiddle.net/Lg0wyt9u/1302

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.