簡體   English   中英

Javascript:將對象從一個數組移動到另一個數組:最佳方法?

[英]Javascript: move objects from one array to another: Best approach?

我有兩個 arrays,分別稱為“對象”和“應用對象”。 我試圖在 Javascript 和/或 Angular 中提出一種優雅的方式來將對象從一個數組移動到另一個數組。

最初我做了這樣的事情:

   $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);
            }
        });
    }

但是后來我意識到,當從循環數組中刪除該值時,它不會添加或刪除所有其他項目,因為它是按索引進行的。

然后我嘗試使用一個臨時數組來保存要添加或刪除的項目列表,我開始遇到奇怪的引用問題。

我開始討論這個問題的最佳解決方案是什么......任何幫助和/或指導將不勝感激。

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);
}

當一個構造自動執行太多操作時(例如 forEach,甚至在這種情況下是 for 循環),請使用更原始的構造,它允許您清楚地說明應該發生什么,而無需解決該構造。 使用 while 循環,您可以表達需要發生的事情,而無需采取備份或以其他方式應用變通方法:

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++;
    }
}

如果你想簡單地移動整個數組,你可以這樣做:

appliedObjects = objects;
objects = []

當然如果它們是函數的參數就行不通了! 否則我看不到除了在循環中復制之外的其他方式,例如

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

或者如果你喜歡短代碼 :) :

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

檢查小提琴http://jsfiddle.net/060ywajm/

您在迭代數組時正在更改數組,您總會錯過一些元素。

一種方法是使用第三個數組來存儲需要從數組中刪除的對象的引用:

// "$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);
});

現在這可能不是一個公平的答案,但如果你注意到你正在做很多復雜的對象/數組操作,你真的應該查看 lodash 或 underscore 庫。 那么你可以用在線解決這個問題:

//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}));

這是我認為對你有用的第一遍。 我正在制作一個測試頁面,以便我可以測試工作的准確性並更新調整后的結果,希望不會有。

編輯:我運行了它,如果我正確理解了問題,它似乎可以滿足您的需求。 我編輯了幾個語法錯誤。

這是帶有壓縮、清理過的代碼的 plunk 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));
});
};

舊代碼

$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));
        });
    };

您可以多次使用此 oneliner 將需要從 arr1 移動到 arr2 的項目數量,只需准備檢查功能

arr2.push(arr1.splice(arr1.findIndex(arr1El => check(arr1El)),1)[0])

您可以使用它來連接 2 個 arrays。 讓 array3 = [...array1, ...array2];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM