Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Short way to replace content of an array

Is there any convenient way to replace the content of an array, AND keep a reference to it? I don't want to replace the array like this:

var arr1 = [1,2,3];
var referenceToArr1 = arr1;
var arr2 = [4,5,6];

arr1 = arr2;
// logs: [4,5,6] false
console.log(arr1, arr1===referenceToArr1);
// logs [1,2,3]
console.log(referenceToArr1);

This way arr1 has the content of arr2, but I loose the reference in referenceToArr1, because it still points to the original arr1.

With this way, I don't loose the reference:

var arr1 = [1,2,3];
var referenceToArr1 = arr1;
var arr2 = [4,5,6];

arr1.length = 0;
for (var i = 0; i < arr2.length; i++) {
  arr1.push(arr2[i]);
}
// logs: [4,5,6] true
console.log(arr1, arr1===referenceToArr1);
// logs: [4,5,6]
console.log(referenceToArr1)

The drawback here is, that I have to empty arr1.length = 0, iterate over every element of arr2 and push it to arr1 by hand.

My questions are:

  • Sure, I could write a helper for this, but what is the most efficient way?
  • Is there a short, vanilla javascript way, to do this (maybe a one liner?)
  • I'm also using underscore.js but haven't found a method for this kind of problem. Is there a way to do this with underscore.js?

Background:

I have an AngularJS app with a service. Inside this service, I have an array to keep all the elements loaded from the server. The data from the service get's bind to a controller and is used in a view. When the data from the service get's change (e.g. a refetch happens), I want to auto update my controllers vars and the view it is bind to.

Here is a Plunker: http://plnkr.co/edit/8yYahwDO6pAuwl6lcpAS?p=preview

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, myService) {
  $scope.name = 'World';
  myService.fetchData().then(function(data) {
    console.log(data)
    $scope.data = data;
  })
});

app.service('myService', function($timeout, $q) {
  var arr;
  var deferred;

  var loadData = function() {
    // here comes some data from the server
    var serverData = [1,2,3];
    arr = serverData;
    deferred.resolve(arr);

    // simulate a refetch of the data
    $timeout(function() {
      var newServerData = [4,5,6];
      // this won't work, because MainCtrl looses it's reference
      // arr = newServerData;
    }, 1000);

    $timeout(function() {
      var newServerData = [7,8,9];
      arr.length = 0;
      [].push.apply(arr, newServerData);
    }, 2000);

    $timeout(function() {
      var newServerData = [10,11,12];
      [].splice.apply(arr, [0, arr.length].concat(newServerData));
    }, 3000);
  }

  return {
    fetchData: function() {
      deferred = $q.defer();

      loadData();

      return deferred.promise;
    }
  }
})

And the view:

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src="https://code.angularjs.org/1.2.16/angular.js" data-semver="1.2.16"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <ul>
      <li ng-repeat="d in data">{{d}}</li>
    </ul>
    3 refetches every second
  </body>

</html>
like image 242
23tux Avatar asked May 06 '14 05:05

23tux


People also ask

How do you replace part of an array?

Replace an Element in an Array using Array.Use the indexOf() method to get the index of the element you want to replace. Call the Array. splice() method to replace the element at the specific index. The array element will get replaced in place.

How do you replace values in an array of objects?

To change the value of an object in an array:Use the Array. map() method to iterate over the array. Check if each object is the one to be updated. Use the spread syntax to update the value of the matching object.

How do you replace multiple elements in an array?

The . splice() method lets you replace multiple elements in an array with one, two, or however many elements you like.


2 Answers

What about this:

// 1. reset the array while keeping its reference
arr1.length = 0;
// 2. fill the first array with items from the second
[].push.apply(arr1, arr2);

See:

  1. How to empty an array in JavaScript?
  2. .push() multiple objects into JavaScript array returns 'undefined'
like image 155
Radim Köhler Avatar answered Sep 18 '22 13:09

Radim Köhler


You can use splice to replace the content of arr1 with the one of arr2 :

[].splice.apply(arr1, [0, arr1.length].concat(arr2));

This way, all references to arr1 would be correctly updated as this would be the same array with a new content.

As you see, that's possible and easy. But there's normally no reason to do this in a well designed program. If the reason is that you're passing an array to different places, then perhaps you should consider embedding this array in an object.

like image 37
Denys Séguret Avatar answered Sep 19 '22 13:09

Denys Séguret