10

I'm hoping to take advantage of underscore to avoid writing for loops throughout my code base. I'm using map in place of a for loop like so:

body.tags = _.map(body.tags, function(tag) {
  return {
    id: tag.id,
    userId: tag.userId,
    createDate: tag.createDate,
    tag: tag.tag.toLowerCase(),
  };
});

My question is, is there a way to do this without specifying the properties that won't be changing (everything but tag)? It seems like overkill to specify fields like id: tag.id.

MattDionis
  • 3,534
  • 10
  • 51
  • 105
  • Is body.tags an array? – Amit Aug 24 '15 at 19:47
  • @Amit, yes `body.tags` is an array of objects, each with the structure shown within the `return` block. – MattDionis Aug 24 '15 at 19:48
  • If you want to continue to use your `_.map` approach, then you could say `return _.extend(tag, { tag: tag.tag.toLowerCase() });`. However, the answer using `forEach` is better. –  Aug 25 '15 at 03:36

2 Answers2

10

You don't even need underscore for this:

body.tags.forEach(function(t) { t.tag = t.tag.toLowerCase();});

map (whether native, underscore or others) is used to transform whole values, it's not a typical use case to do what you tried to do with it. Also, using a simple for might perform better since you don't need function calls here, but that depends on runtime optimizations.

By the way, if you replace the mapping function with the function from this answer and not set the return value back to body.tags, you'll also get your desired result.

Amit
  • 45,440
  • 9
  • 78
  • 110
  • this is the right answer, you can use underscore / lodash to find the objects you want to manipulate. for would be faster, but if you don't have millions of items it's ok to do it the easy way ;) – webdeb Aug 24 '15 at 19:55
  • Although it is always nicer to use immutability & not modify the same object, instead use a new one if it is not too much hassle of deep cloning. – Priya Ranjan Singh May 06 '20 at 18:36
8

You could try the following code to change a single property in a collection using underscore.

_.map(body.tags, function(tag) {
    tag.tag = tag.tag.toLowerCase();
    return tag;
});

There is one benefit in using lodash's map method (similar to underscore library) over native forEach and its performance. Based on why lodash is faster than native forEach post, maybe it's justifiable to use lodash in favour of both underscore and native forEach to loop. However I would agree with the user who commented below "Choose the approach that is most writable, readable, and maintainable".

Community
  • 1
  • 1
invalidred
  • 179
  • 1
  • 6
  • 1
    Why should the OP "try this"? A good answer will always have an explanation of what was done and why it was done that way, not only for the OP but for future visitors to SO. – Jay Blanchard Aug 24 '15 at 21:12
  • 1
    Thanks for the feedback Jay Blanchard. I agree with what you've said. I was just answering the question asked by OP. Clearly I wasn't thinking from the perspective of future visitors. I will keep that in mind hence forth. – invalidred Aug 25 '15 at 03:18
  • 2
    This won't work, because the function passed to map doesn't return anything. By the way, performance is the last reason to choose one alternative over another. Choose the approach that is most writable, readable, and maintainable. –  Aug 25 '15 at 03:32
  • thanks for pointing out the mistake torazabouro, i have updated the code. – invalidred Aug 25 '15 at 17:57