7

Is there an easy way to replace all appearances of an primitive in an array with another one. So that ['a', 'b', 'a', 'c'] would become ['x', 'b', 'x', 'c'] when replacing a with x. I'm aware that this can be done with a map function, but I wonder if have overlooked a simpler way.

Andreas Köberle
  • 98,250
  • 56
  • 262
  • 287
  • I think the purpose of a library like Lo-Dash is not to enable you to write the most code-golfy solution you can possibly write, but to write the most natural and idiomatic solution. And what could be more natural and idiomatic than `map()` in this case? It's the *perfect* tool for the job. – Tomalak Nov 08 '13 at 14:46
  • @Tomalak `_(array).filter('someKey').replace('a', 'x')` looks very natural to me – Andreas Köberle Nov 08 '13 at 14:57
  • 1
    But that would not be logical - I would expect an operation named "filter" to reduce number of elements in the input. Also: It's not about the looks. It's about the *operation* you want to perform on the data, and to me that is "mapping a list of N values a list of N values (some of which by accident happen to be the same as the input)". – Tomalak Nov 08 '13 at 15:08
  • Use findIndex from Lodash then replace the element at the found index – Gibrahh Mar 09 '19 at 07:23

4 Answers4

11

In the specific case of strings your example has, you can do it natively with:

myArr.join(",").replace(/a/g,"x").split(",");

Where "," is some string that doesn't appear in the array.

That said, I don't see the issue with a _.map - it sounds like the better approach since this is in fact what you're doing. You're mapping the array to itself with the value replaced.

_.map(myArr,function(el){
     return (el==='a') ? 'x' : el;
})
Benjamin Gruenbaum
  • 260,410
  • 85
  • 489
  • 489
  • 2
    The question was about primitives not just strings. Also I want to use lodash, as this will be one step in a longer chain, where the array data is manipulated in. – Andreas Köberle Nov 08 '13 at 13:23
  • @AndreasKöberle First of all using a particular library is a mean and not a goal. Second of all - in that case `_.map` is what you're looking for, underscore/lodash has no specific replace/swap functionality on collections, you can add it to the lodash prototype yourself if you'd like. – Benjamin Gruenbaum Nov 08 '13 at 13:26
  • 2
    _.map is really fit to this use case, there's no need to look for anything else. – Denys Séguret Nov 12 '13 at 07:56
3

I don't know about "simpler", but you can make it reusable

function swap(ref, replacement, input) {
    return (ref === input) ? replacement : input;
}

var a = ['a', 'b', 'a', 'c'];

_.map(a, _.partial(swap, 'a', 'x'));
Tomalak
  • 322,446
  • 66
  • 504
  • 612
3

If the array contains mutable objects, It's straightforward with lodash's find function.

  var arr = [{'a':'a'}, {'b':'b'},{'a':'a'},{'c':'c'}];    

  while(_.find(arr, {'a':'a'})){
    (_.find(arr, {'a':'a'})).a = 'x';
  }


console.log(arr); // [{'a':'x'}, {'b':'b'},{'a':'x'},{'c':'c'}]
j1s
  • 151
  • 2
  • 17
1

Another simple solution. Works well with arrays of strings, replaces all the occurrences, reads well.

var arr1 = ['a', 'b', 'a', 'c'];
var arr2 = _.map(arr1, _.partial(_.replace, _, 'a', 'd'));
console.log(arr2); // ["d", "b", "d", "c"]
Ihor
  • 2,498
  • 2
  • 14
  • 19