javascript - sort - js array remove




在JavaScript中按值複製數組 (14)

slice()的替代方案是concat ,可以以兩種方式使用。 其中第一個可能更具可讀性,因為預期的行為非常明確:

var array2 = [].concat(array1);

第二種方法是:

var array2 = array1.concat();

科恩(在評論中)指出,後一種方法有更好的表現

這種方式的工作原理是, concat方法創建一個新的數組,其中包含調用該對象的對像中的元素,隨後是傳遞給它的任何數組的元素作為參數。 所以當沒有參數傳遞時,它只是複制數組。

Lee Penkman也在評論中指出,如果array1 undefined ,你可以按如下方式返回一個空數組:

var array2 = [].concat(array1 || []);

或者,對於第二種方法:

var array2 = (array1 || []).concat();

請注意,您也可以使用slice進行此操作: var array2 = (array1 || []).slice();

將JavaScript中的數組複製到另一個數組時:

var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d');  //Now, arr1 = ['a','b','c','d']

我意識到arr2是指與arr1相同的數組,而不是一個新的獨立數組。 我如何復制數組來獲得兩個獨立的數組?


上面提到的一些方法在使用簡單數據類型(如數字或字符串)時工作良好,但當數組包含其他對象時,這些方法會失敗。 當我們試圖從一個數組向另一個數組傳遞任何對象時,它將作為引用傳遞,而不是對象。

在您的JavaScript文件中添加以下代碼:

Object.prototype.clone = function() {
    var newObj = (this instanceof Array) ? [] : {};
    for (i in this) {
        if (i == 'clone') 
            continue;
        if (this[i] && typeof this[i] == "object") {
            newObj[i] = this[i].clone();
        } 
        else 
            newObj[i] = this[i]
    } return newObj;
};

並簡單地使用

var arr1 = ['val_1','val_2','val_3'];
var arr2 = arr1.clone()

它會工作。


在Javascript中,深度複製技術依賴於數組中的元素。
我們從這裡開始。

三種元素

元素可以是:文字值,文字結構或原型。

// Literal values (type1)
var booleanLiteral = true;
var numberLiteral = 1;
var stringLiteral = 'true';

// Literal structures (type2)
var arrayLiteral = [];
var objectLiteral = {};

// Prototypes (type3)
var booleanPrototype = new Bool(true);
var numberPrototype = new Number(1);
var stringPrototype = new String('true');
var arrayPrototype = new Array();
var objectPrototype = new Object(); # or "new function () {}"

從這些元素我們可以創建三種類型的數組。

// 1) Array of literal-values (boolean, number, string) 
var type1 = [true, 1, "true"];

// 2) Array of literal-structures (array, object)
var type2 = [[], {}];

// 3) Array of prototype-objects (function)
var type3 = [function () {}, function () {}];

深度複製技術取決於三種陣列類型

根據數組中的元素類型,我們可以使用各種技術進行深度複製。

  • 字面值數組(type1)
    可以使用myArray.splice(0)myArray.slice()myArray.concat()技術來僅使用文字值(布爾值,數字和字符串)深度複製數組; 其中Slice比Concat具有更高的性能( http://jsperf.com/duplicate-array-slice-vs-concat/3 )。

  • 文字值(類型1)和文字結構(類型2)
    JSON.parse(JSON.stringify(myArray))技術可用於深度複製文字值(布爾,數字,字符串)和文字結構(數組,對象),但不能用於原型對象。

  • 所有數組(type1,type2,type3)
    jQuery $.extend(myArray)技術可用於深度複製所有數組類型。 像UnderscoreLo-dash這樣的庫為jQuery $.extend()提供了類似的深層複製功能,但性能較低。 更令人驚訝的是, $.extend()JSON.parse(JSON.stringify(myArray))技術具有更高的性能http://jsperf.com/js-deep-copy/15
    對於那些迴避第三方庫(比如jQuery)的開發者,你可以使用下面的自定義函數; 它比$ .extend具有更高的性能,並且可以深度複製所有陣列。

    function copy(o) {
      var output, v, key;
      output = Array.isArray(o) ? [] : {};
      for (key in o) {
        v = o[key];
        output[key] = (typeof v === "object" && v !== null) ? copy(v) : v;
      }
      return output;
    }  
    

所以要回答這個問題......

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

我意識到arr2是指與arr1相同的數組,而不是一個新的獨立數組。 我如何復制數組來獲得兩個獨立的數組?

回答

由於arr1是字面值(布爾值,數字或字符串)的數組,因此您可以使用上面討論的任何深度複製技術,其中slice具有最高的性能。

// Highest performance for deep copying literal values
arr2 = arr1.slice();

// Any of these techniques will deep copy literal values as well,
//   but with lower performance.
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // Custom-function needed - as provided above

在我的情況下,我需要確保陣列保持完好,所以這對我有效:

// Empty array
arr1.length = 0;
// Add items from source array to target array
for (var i = 0; i < arr2.length; i++) {
    arr1.push(arr2[i]);
}

如果要製作對像或數組的新副本,則必須顯式複制對象的屬性或數組的元素,例如:

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

for (var i=0; i < arr1.length; i++) {
   arr2[i] = arr1[i];
}

您可以在Google上搜索有關不可變原始值和可變對象引用的更多信息。


從ES2015開始,

var arr2 = [...arr1];

您可以使用數組傳播...來複製數組。

const itemsCopy = [...items];

此外,如果想創建一個新的數組,現有的數組是其中的一部分:

var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];

現在所有主流瀏覽器支持數組傳播,但如果您需要較早的支持,請使用打字稿或babel並編譯為ES5。

developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…


我個人認為Array.from是一個更可讀的解決方案。 順便說一下,只要注意它的瀏覽器支持。

//clone
let x = [1,2,3];
let y = Array.from(x);

//deep clone
let clone = arr => Array.from(arr,item => Array.isArray(item) ? clone(item) : item);
let x = [1,[],[[]]];
let y = clone(x);

正如我們在Javascript中所知道的, 數組像是通過引用的,但是我們可以通過什麼方式複制數組而不更改原始數組呢?

這裡有幾個方法來做到這一點:

想像一下,我們在你的代碼中有這個數組:

var arr = [1, 2, 3, 4, 5];

1)在函數中循環訪問數組並返回一個新數組,如下所示:

 function newArr(arr) {
      var i=0, res = [];
      while(i<arr.length){
       res.push(arr[i]);
        i++;
       }
   return res;
 }

2)使用slice方法,slice用於對數組的一部分進行切片,如果不指定數組的開始和結束,它將切片數組的一部分而不接觸原始數據,如果不指定數組的開始和結束,它將切片整個數組並基本上完成數組的完整副本,所以我們可以輕鬆地說:

var arr2 = arr.slice(); // make a copy of the original array

3)也聯繫方法,這是為了合併兩個數組,但我們可以指定一個數組,然後基本上在新的聯繫數組中創建一個值的副本:

var arr2 = arr.concat();

4)也對字符串化和解析方法進行字符串分析,不建議這樣做,但可以簡單地複制數組和對象:

var arr2 = JSON.parse(JSON.stringify(arr));

5)Array.from方法,這並沒有得到廣泛的支持,在使用前請檢查不同瀏覽器的支持情況:

var arr2 = Array.from(arr);

6)ECMA6的方式,也不完全支持,但babelJs可以幫助你,如果你想transpile:

let arr2 = [...arr];

沒有jQuery需要... 工作示例

var arr2 = arr1.slice()

這複製了從開始位置0到數組末尾的數組。

重要的是要注意,它將按照原始類型(字符串,數字等)的預期工作,並解釋引用類型的預期行為。

如果你有一個Reference類型的數組,比如Object類型。 該數組被複製,但是兩個數組都將包含對同一個Object的引用。 所以在這種情況下,即使數組實際被複製,看起來數組仍被引用複制。


用這個:

var newArray = oldArray.slice();

基本上, slice()操作克隆數組並將引用返回給新數組。 另請注意:

對於引用,字符串和數字(而不是實際對象),切片將對象引用複製到新數組中。 原始數組和新數組都指向同一個對象。 如果引用的對象發生更改,則這些更改對新數組和原始數組均可見。

字符串和數字等原語是不可變的,因此對字符串或數字的修改是不可能的。


複製多維數組/對象:

function deepCopy(obj) {
   if (Object.prototype.toString.call(obj) === '[object Array]') {
      var out = [], i = 0, len = obj.length;
      for ( ; i < len; i++ ) {
         out[i] = arguments.callee(obj[i]);
      }
      return out;
   }
   if (typeof obj === 'object') {
      var out = {}, i;
      for ( i in obj ) {
         out[i] = arguments.callee(obj[i]);
      }
      return out;
   }
   return obj;
}

感謝James Padolsey提供此功能。

來源: Here


這是我嘗試了很多方法之後做到的:

var newArray = JSON.parse(JSON.stringify(orgArray));

這將創建一個與第一個不相關的新的深層副本(不是淺表副本)。

此外,這顯然不會克隆事件和函數,但是您可以在一行中完成這件事,它可以用於任何類型的對象(數組,字符串,數字,對象...)


這裡有幾種複制方式:

const array = [1,2,3,4];

const arrayCopy1 = Object.values(array);
const arrayCopy2 = Object.assign([], array);
const arrayCopy3 = array.map(i => i);
const arrayCopy4 = Array.of(...array );





arrays