is there a function in lodash to replace matched item

前端 未结 15 2277
孤街浪徒
孤街浪徒 2020-12-07 13:42

I wonder if there is a simpler method in lodash to replace an item in a JavaScript collection? (Possible duplicate but I did not understand the answer there:)

I look

相关标签:
15条回答
  • 2020-12-07 14:24
    function findAndReplace(arr, find, replace) {
      let i;
      for(i=0; i < arr.length && arr[i].id != find.id; i++) {}
      i < arr.length ? arr[i] = replace : arr.push(replace);
    }
    

    Now let's test performance for all methods:

    // TC's first approach
    function first(arr, a, b) {
      _.each(arr, function (x, idx) {
        if (x.id === a.id) {
          arr[idx] = b;
          return false;
        }
      });
    }
    
    // solution with merge
    function second(arr, a, b) {
      const match = _.find(arr, a);
      if (match) {
        _.merge(match, b);
      } else {
        arr.push(b);
      }
    }
    
    // most voted solution
    function third(arr, a, b) {
      const match = _.find(arr, a);
      if (match) {
        var index = _.indexOf(arr, _.find(arr, a));
        arr.splice(index, 1, b);
      } else {
        arr.push(b);
      }
    }
    
    // my approach
    function fourth(arr, a, b){
      let l;
      for(l=0; l < arr.length && arr[l].id != a.id; l++) {}
      l < arr.length ? arr[l] = b : arr.push(b);
    }
    
    function test(fn, times, el) {
      const arr = [], size = 250;
      for (let i = 0; i < size; i++) {
        arr[i] = {id: i, name: `name_${i}`, test: "test"};
      }
    
      let start = Date.now();
      _.times(times, () => {
        const id = Math.round(Math.random() * size);
        const a = {id};
        const b = {id, name: `${id}_name`};
        fn(arr, a, b);
      });
      el.innerHTML = Date.now() - start;
    }
    
    test(first, 1e5, document.getElementById("first"));
    test(second, 1e5, document.getElementById("second"));
    test(third, 1e5, document.getElementById("third"));
    test(fourth, 1e5, document.getElementById("fourth"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script>
    <div>
      <ol>
        <li><b id="first"></b> ms [TC's first approach]</li>
        <li><b id="second"></b> ms [solution with merge]</li>
        <li><b id="third"></b> ms [most voted solution]</li>
        <li><b id="fourth"></b> ms [my approach]</li>
      </ol>
    <div>

    0 讨论(0)
  • 2020-12-07 14:24

    If the insertion point of the new object does not need to match the previous object's index then the simplest way to do this with lodash is by using _.reject and then pushing new values in to the array:

    var arr = [
      { id: 1, name: "Person 1" }, 
      { id: 2, name: "Person 2" }
    ];
    
    arr = _.reject(arr, { id: 1 });
    arr.push({ id: 1, name: "New Val" });
    
    // result will be: [{ id: 2, name: "Person 2" }, { id: 1, name: "New Val" }]
    

    If you have multiple values that you want to replace in one pass, you can do the following (written in non-ES6 format):

    var arr = [
      { id: 1, name: "Person 1" }, 
      { id: 2, name: "Person 2" }, 
      { id: 3, name: "Person 3" }
    ];
    
    idsToReplace = [2, 3];
    arr = _.reject(arr, function(o) { return idsToReplace.indexOf(o.id) > -1; });
    arr.push({ id: 3, name: "New Person 3" });
    arr.push({ id: 2, name: "New Person 2" });
    
    
    // result will be: [{ id: 1, name: "Person 1" }, { id: 3, name: "New Person 3" }, { id: 2, name: "New Person 2" }]
    
    0 讨论(0)
  • 2020-12-07 14:29

    You can do it without using lodash.

    let arr = [{id: 1, name: "Person 1"}, {id: 2, name: "Person 2"}];
    let newObj = {id: 1, name: "new Person"}
    
    /*Add new prototype function on Array class*/
    Array.prototype._replaceObj = function(newObj, key) {
      return this.map(obj => (obj[key] === newObj[key] ? newObj : obj));
    };
    
    /*return [{id: 1, name: "new Person"}, {id: 2, name: "Person 2"}]*/
    arr._replaceObj(newObj, "id") 
    
    0 讨论(0)
提交回复
热议问题