Javascript: moving objects from one array to another: better approach?

I have two arrays called "objects" and "application objects". I am trying to come up with an elegant way in Javascript and / or Angular to move objects from one array to another.

At first I did something like this:

$scope.remove = function () { angular.forEach($scope.appliedObjects, function (element, index) { if (element.selected) { element.selected = false; $scope.objects.push(element); $scope.appliedObjects.splice(index, 1); } }); } $scope.add= function () { angular.forEach($scope.objects, function (element, index) { if (element.selected) { element.selected = false; $scope.appliedObjects.push(element); $scope.objects.splice(index, 1); } }); } 

But then I realized that when the value was removed from the loop of the loop, and it won’t add or remove every other element, as it went through the index.

Then I tried to use a temporary array to store a list of items that need to be added or removed, and I started getting strange reference problems.

I'm starting to think a bit about what the best solution for this problem would be ... any help and / or guidance would be greatly appreciated.

+5
source share
6 answers
 function moveElements(source, target, moveCheck) { for (var i = 0; i < source.length; i++) { var element = source[i]; if (moveCheck(element)) { source.splice(i, 1); target.push(element); i--; } } } function selectionMoveCheck(element) { if (element.selected) { element.selected = false; return true; } } $scope.remove = function () { moveElements($scope.appliedObjects, $scope.objects, selectionMoveCheck); } $scope.add = function () { moveElements($scope.objects, $scope.appliedObjects, selectionMoveCheck); } 
+8
source

When a construct does too much automatically (e.g. forEach or even a for-loop, in this case), use a more primitive construct that allows you to tell what needs to happen clearly, without having to bypass the construct. Using the while loop, you can express what should happen without having to back up or otherwise use workarounds:

  function moveSelected(src, dest) { var i = 0; while ( i < src.length ) { var item = src[i]; if (item.selected) { src.splice(i,1); dest.push(item); } else i++; } } 
+3
source

If you want to just move the whole array, you can do:

 appliedObjects = objects; objects = [] 

Of course, this would not work if they were function parameters! Otherwise, I see no other way than copying in a loop, for example.

 while (objects.length) { appliedObjects.push(objects[0]); objects.splice(0,1); } 

or if you need a short code :):

 while (objects.length) appliedObjects.push(objects.splice(0,1)); 

check fiddle http://jsfiddle.net/060ywajm/

0
source

You modify the array during iteration on it, you will always skip some elements.

One way to do this is to use a third array to store references to objects that need to be removed from the array:

 // "$scope.add" case var objectsToRemove = []; $scope.objects.forEach(function (value) { if (value.selected) { value.selected = false; $scope.appliedObjects.push(value); objectsToRemove.push(value); } }); objectsToRemove.forEach(function (value) { $scope.objects.splice($scope.objects.indexOf(value), 1); }); 
0
source

Now this may not be a fair answer, but if you notice that you are doing a lot of complex manipulations with the object / array, you should really check out the lodash or underscore library. then you can solve it with the liner:

 //lodash remove function appliedObjects.push.apply( appliedObjects, _.remove(objects, { 'selected': true})); //or if you want to insert in the beginning of the list: appliedObjects.splice(0, 0, _.remove(objects, { 'selected': true})); 
0
source

This first pass, in my opinion, will work for you. I am in the process of creating a test page to check the accuracy and update the modified result, which I hope will not be.

EDIT: I ran it and it seems to have done what you want if I understood the problem correctly. There were a few syntax errors that I edited.

Here's a tablet with a condensed, cleaned code http://plnkr.co/edit/K7XuMu?p=preview

HTML

 <button ng-click="transferArrays(objects, appliedObjects)">Add</button> <button ng-click="transferArrays(appliedObjects, objects)">Remove</button> 

Js

 $scope.transferArrays = function (arrayFrom, arrayTo) { var selectedElements; selectedElements = []; angular.forEach(arrayFrom, function(element) { if (element.isSelected) { element.isSelected = false; selectedElements.push(element); } }); angular.forEach(selectedElements, function(element) { arrayTo.push(arrayFrom.splice( arrayFrom.map(function(x) { return x.uniqueId; }) .indexOf(element.uniqueId), 1)); }); }; 

Old code

 $scope.remove = function () { var selectedElements; selectedElements = []; angular.forEach($scope.appliedObjects, function (element) { if (element.isSelected) { element.isSelected = false; selectedElements.push(element); } }); angular.forEach(selectedElements, function (element) { $scope.objects.push($scope.appliedObjects.splice( $scope.appliedObjects.map(function (x) { return x.uniqueId; }) .indexOf(element.uniqueId), 1)); }); }; $scope.add = function () { var selectedElements; selectedElements = []; angular.forEach($scope.objects, function (element) { if (element.isSelected) { element.isSelected = false; selectedElements.push(element); } }); angular.forEach(selectedElements, function (element) { $scope.appliedObjects.push($scope.objects.splice( $scope.objects.map(function (x) { return x.uniqueId; }) .indexOf(element.uniqueId), 1)); }); }; 
0
source

All Articles