01.數組的高級方法

數組是我們使用十分頻繁的一種數據類型,是否能夠熟練掌握數組的高級方法,將會直接影響我們的工作效率。在開始本文之前,小伙伴們可以先看下之前關于數組遍歷的文章,里面的內容在本文中將不會再贅述:

一.過濾方法 filter

**filter()** 方法創建一個新數組, 其包含通過所提供函數實現的測試的所有元素。 、

var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])

1.1 參數

  • callback

    用來測試數組的每個元素的函數。返回 true 表示該元素通過測試,保留該元素,false 則不保留。它接受以下三個參數:

    element數組中當前正在處理的元素。index可選正在處理的元素在數組中的索引。array可選調用了 filter 的數組本身。

  • thisArg可選

    執行 callback 時,用于 this 的值。

1.2 返回值

一個新的、由通過測試的元素組成的數組,如果沒有任何數組元素通過測試,則返回空數組。

  • filter 不會改變原數組,它返回過濾后的新數組。

1.3 描述

filter 為數組中的每個元素調用一次 callback 函數,并利用所有使得 callback 返回 true 或等價于 true 的值的元素創建一個新數組。callback 只會在已經賦值的索引上被調用,對于那些已經被刪除或者從未被賦值的索引不會被調用。那些沒有通過 callback 測試的元素會被跳過,不會被包含在新數組中。

callback 被調用時傳入三個參數:

  1. 元素的值
  2. 元素的索引
  3. 被遍歷的數組本身

如果為 filter 提供一個 thisArg 參數,則它會被作為 callback 被調用時的 this 值。否則,callbackthis 值在非嚴格模式下將是全局對象,嚴格模式下為 undefinedcallback 函數最終觀察到的 this 值是根據通常函數所看到的 "this"的規則確定的。

1.4 例子:數組大于5的人

 // filter案例:選出數組中大于五的數
 let arr = [5, 6, 8, 10, 24];
 let bigThanEightArr = arr.filter((item, index, arr) => {
 // console.log(item, index, arr);
 return item > 6
 }, this);
 console.log(bigThanEightArr); //[8,10,24]

上面的代碼是 filter 方法的使用方式,filter 接收兩個參數,并最終返回一個新的數組。filter 的兩個參數分別是:

第一個是回調函數。回調函數有三個參數分別當前的元素、當前元素的索引、原數組,可以在回調函數中進行一些操作,從而判斷是否要保留這個元素,如果要保留,則回調函數需要返回 true ,反之則返回 false

在上面的代碼中,只要當前的元素大于 5 ,item > 5 就會返回 true ,從而將該值保留,因此將原數組過濾后的新數組是 [6, 8, 9]

第二個參數用于指定回調函數執行時,this 的指向。上面的代碼中并沒有設置該參數,因此在回調中打印 this 時,其指向為 window 對象

二.加工方法map

**map()** 方法創建一個新數組,其結果是該數組中的每個元素是調用一次提供的函數后的返回值。

var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])

2.1 參數

  • callback生成新數組元素的函數,使用三個參數:
  • currentValue:callback數組中正在處理的當前元素。
  • index可選:callback 數組中正在處理的當前元素的索引。
  • array可選:map 方法調用的數組。
  • thisArg可選:執行 callback 函數時值被用作this

2.2 返回值

一個由原數組每個元素執行回調函數的結果組成的新數組。

2.3 案例:map案例:將原數組每個元素都乘以2

// map案例:將原數組每個元素都乘以2
let doubleArr = arr.map((item, index, arr) => item * 2);
console.log(doubleArr); //[10, 12, 16, 20, 48]

2.4 以下代碼使用一個包含對象的數組來重新創建一個格式化后的數組。

var kvArray = [{key: 1, value: 10},
               {key: 2, value: 20},
               {key: 3, value: 30}];

var reformattedArray = kvArray.map(function(obj) {
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});

// reformattedArray 數組為: [{1: 10}, {2: 20}, {3: 30}],

// kvArray 數組未被修改:
// [{key: 1, value: 10},
//  {key: 2, value: 20},
//  {key: 3, value: 30}]

三.reduce

3.1 參數

callback

執行數組中每個值 (如果沒有提供 initialValue則第一個值除外)的函數,包含四個參數:

accumulator

  • currentValue

    數組中正在處理的元素。

  • index 可選

    數組中正在處理的當前元素的索引。 如果提供了initialValue,則起始索引號為0,否則從索引1起始。

  • array可選

    調用reduce()的數組

initialValue可選

作為第一次調用 callback函數時的第一個參數的值。 如果沒有提供初始值,則將使用數組中的第一個元素。 在沒有初始值的空數組上調用 reduce 將報錯。

3.2 返回值

函數累計處理的結果

3.3 描述

reduce為數組中的每一個元素依次執行callback函數,不包括數組中被刪除或從未被賦值的元素,接受四個參數:

  • accumulator 累計器
  • currentValue 當前值
  • currentIndex 當前索引
  • array 數組

回調函數第一次執行時,accumulatorcurrentValue的取值有兩種情況:

  • ==如果調用reduce()時提供了initialValueaccumulator取值為initialValuecurrentValue取數組中的第一個值;==
  • ==如果沒有提供 initialValue,那么accumulator取數組中的第一個值,currentValue取數組中的第二個值。==

注意:如果沒有提供initialValue,reduce 會從索引1的地方開始執行 callback 方法,跳過第一個索引。如果提供initialValue,從索引0開始。

如果數組為空且沒有提供initialValue,會拋出TypeError(無論位置如何)并且沒有提供initialValue, 或者有提供initialValue但是數組為空,那么此唯一值將被返回并且callback不會被執行。

3.4 reduce是如何運行的?

假如運行下段reduce()代碼:

[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){
  return accumulator + currentValue;
});

callback 被調用四次,每次調用的參數和返回值如下表:

callback accumulator currentValue currentIndex array return value
first call 0 1 1 [0, 1, 2, 3, 4] 1
second call 1 2 2 [0, 1, 2, 3, 4] 3
third call 3 3 3 [0, 1, 2, 3, 4] 6
fourth call 6 4 4 [0, 1, 2, 3, 4] 10

reduce返回的值將是最后一次回調返回值(10)。

你還可以使用箭頭函數來代替完整的函數。 下面的代碼將產生與上面的代碼相同的輸出:

[0, 1, 2, 3, 4].reduce((prev, curr) => prev + curr );

如果你打算提供一個初始值作為reduce()方法的第二個參數,以下是運行過程及結果:

[0, 1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => {
    return accumulator + currentValue
}, 10)
callback accumulator currentValue currentIndex array return value
first call 10 0 0 [0, 1, 2, 3, 4] 10
second call 10 1 1 [0, 1, 2, 3, 4] 11
third call 11 2 2 [0, 1, 2, 3, 4] 13
fourth call 13 3 3 [0, 1, 2, 3, 4] 16
fifth call 16 4 4 [0, 1, 2, 3, 4] 20

這種情況下reduce()返回的值是20

3.4 reduce練習

3.4.1沒有 有原始參數

 //  1.reduce沒有原始參數
    let arr = [10, 15, 8, 6, 11, false, 'hello'];

    let newArr = arr.reduce((previousValue, currentValue, index, arr) => {
      console.log(previousValue, currentValue, index, arr);
      return previousValue = previousValue + currentValue;
    })
    console.log(newArr); //50hello

3.4.2 有原始參數

 // 2.reduce有原始參數
    let newArr2 = arr.reduce((previousValue, currentValue, index, arr) => {
      return previousValue += currentValue;
    }, 10);
    console.log(newArr2); //60hello

3.4.3 累加對象數組里的值

要累加對象數組中包含的值,必須提供初始值,以便各個item正確通過你的函數。

var initialValue = 0;
var sum = [{x: 1}, {x:2}, {x:3}].reduce(
    (accumulator, currentValue) => accumulator + currentValue.x
    ,initialValue
);

console.log(sum) // logs 6

3.4.4 將二維數組轉化為一維

var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
  function(a, b) {
    return a.concat(b);
  },
  []
);
// flattened is [0, 1, 2, 3, 4, 5]

四.查找數組的元素(find)

**find()** 方法返回數組中滿足提供的測試函數的第一個元素的值。否則返回 undefined

4.1語法

arr.find(callback[, thisArg])

4.2 參數

  • callback

    在數組每一項上執行的函數,接收 3 個參數:element當前遍歷到的元素。index可選當前遍歷到的索引。array可選數組本身。

  • thisArg可選

    執行回調時用作this 的對象。

4.3 返回值

數組中第一個滿足所提供測試函數的元素的值,否則返回 undefined

4.4 描述

find方法對數組中的每一項元素執行一次 callback 函數,直至有一個 callback 返回 true。當找到了這樣一個元素后,該方法會立即返回這個元素的值,否則返回 undefined。注意 callback函數會為數組中的每個索引調用即從 0length - 1,而不僅僅是那些被賦值的索引,這意味著對于稀疏數組來說,該方法的效率要低于那些只遍歷有值的索引的方法。

callback函數帶有3個參數:當前元素的值、當前元素的索引,以及數組本身。

如果提供了 thisArg參數,那么它將作為每次 callback函數執行時的this ,如果未提供,則使用 undefined

find方法不會改變數組。

在第一次調用 callback函數時會確定元素的索引范圍,因此在 find方法開始執行之后添加到數組的新元素將不會被 callback函數訪問到。如果數組中一個尚未被callback函數訪問到的元素的值被callback函數所改變,那么當callback函數訪問到它時,它的值是將是根據它在數組中的索引所訪問到的當前值。被刪除的元素仍舊會被訪問到,但是其值已經是undefined了。

4.5 案例

let arr = [10, 5, 6, 80, 12];
let element = arr.find((currentValue, index, arr) => {
    return currentValue > 70
})
console.log(element); //80

五. 查找數組元素的索引(findIndex)

indIndex()方法返回數組中滿足提供的測試函數的第一個元素的索引。若沒有找到對應元素則返回-1。

5.1語法

arr.findIndex(callback[, thisArg])

5.2參數

  • callback

    針對數組中的每個元素, 都會執行該回調函數, 執行時會自動傳入下面三個參數:element當前元素。index當前元素的索引。array調用findIndex的數組。

  • thisArg

    可選。執行callback時作為this對象的值.

5.3 返回值

數組中通過提供測試函數的第一個元素的索引。否則,返回-1

5.4 描述

findIndex方法對數組中的每個數組索引0..length-1(包括)執行一次callback函數,直到找到一個callback函數返回真實值(強制為true)的值。如果找到這樣的元素,findIndex會立即返回該元素的索引。如果回調從不返回真值,或者數組的length為0,則findIndex返回-1。 與某些其他數組方法(如Array#some)不同,在稀疏數組中,即使對于數組中不存在的條目的索引也會調用回調函數。

回調函數調用時有三個參數:元素的值,元素的索引,以及被遍歷的數組。

如果一個 thisArg 參數被提供給 findIndex, 它將會被當作this使用在每次回調函數被調用的時候。如果沒有被提供,將會使用undefined

findIndex不會修改所調用的數組。

在第一次調用callback函數時會確定元素的索引范圍,因此在findIndex方法開始執行之后添加到數組的新元素將不會被callback函數訪問到。如果數組中一個尚未被callback函數訪問到的元素的值被callback函數所改變,那么當callback函數訪問到它時,它的值是將是根據它在數組中的索引所訪問到的當前值。被刪除的元素仍然會被訪問到。

5.5 查找數組中首個質數元素的索引

 // 以下示例查找數組中素數的元素的索引(如果不存在素數,則返回-1)。
    function isPrime(element, index, array) {
      var start = 2;
      while (start <= Math.sqrt(element)) { //獲取平方根
        if (element % start++ < 1) {
          return false;
        }
      }
      return element > 1;
    }

    console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not found
    console.log([4, 6, 7, 12].findIndex(isPrime)); // 2

六.判斷方法:==至少有1個元素==通過了被提供的函數測試(some)

**some()** 方法測試數組中是不是至少有1個元素通過了被提供的函數測試。它返回的是一個Boolean類型的值。

注意:如果用一個空數組進行測試,在任何情況下它返回的都是false

6.1語法

arr.some(callback(element[, index[, array]])[, thisArg])

6.2參數

  • callback

    用來測試每個元素的函數,接受三個參數:element數組中正在處理的元素。index 可選數組中正在處理的元素的索引值。array可選some()被調用的數組。

  • thisArg可選

    執行 callback 時使用的 this 值。

6.3 返回值

數組中有至少一個元素通過回調函數的測試就會返回true;所有元素都沒有通過回調函數的測試返回值才會為false。

6.4 描述

some() 為數組中的每一個元素執行一次 callback 函數,直到找到一個使得 callback 返回一個“真值”(即可轉換為布爾值 true 的值)。如果找到了這樣一個值,some() 將會立即返回 true。否則,some() 返回 falsecallback 只會在那些”有值“的索引上被調用,不會在那些被刪除或從來未被賦值的索引上調用。

callback 被調用時傳入三個參數:元素的值,元素的索引,被遍歷的數組。

如果一個thisArg參數提供給some(),它將被用作調用的 callbackthis 值。否則, 它的 this value將是 undefinedthis的值最終通過callback來觀察,根據 the usual rules for determining the this seen by a function的this判定規則來確定。

some() 被調用時不會改變數組。

some() 遍歷的元素的范圍在第一次調用 callback. 前就已經確定了。在調用 some() 后被添加到數組中的值不會被 callback 訪問到。如果數組中存在且還未被訪問到的元素被 callback 改變了,則其傳遞給 callback 的值是 some() 訪問到它那一刻的值。已經被刪除的元素不會被訪問到。

6.5 案例

6.5.1 測試數組元素的值

下面的例子檢測在數組中是否有元素大于 10。

function isBiggerThan10(element, index, array) {
  return element > 10;
}

[2, 5, 8, 1, 4].some(isBiggerThan10);  // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true

6.5.2 使用箭頭函數測試數組元素的值

箭頭函數 可以通過更簡潔的語法實現相同的用例.

[2, 5, 8, 1, 4].some(x => x > 10);  // false
[12, 5, 8, 1, 4].some(x => x > 10); // true

6.5.3 判斷數組元素中是否存在某個值

此例中為模仿 includes() 方法, 若元素在數組中存在, 則回調函數返回值為 true :

var fruits = ['apple', 'banana', 'mango', 'guava'];

function checkAvailability(arr, val) {
  return arr.some(function(arrVal) {
    return val === arrVal;
  });
}

checkAvailability(fruits, 'kela');   // false
checkAvailability(fruits, 'banana'); // true

6.5.4 使用箭頭函數判斷數組元素中是否存在某個值

var fruits = ['apple', 'banana', 'mango', 'guava'];

function checkAvailability(arr, val) {
  return arr.some(arrVal => val === arrVal);
}

checkAvailability(fruits, 'kela');   // false
checkAvailability(fruits, 'banana'); // true

6.5.5 將任意值轉換為布爾類型

var TRUTHY_VALUES = [true, 'true', 1];

function getBoolean(value) {
  'use strict';

  if (typeof value === 'string') {
    value = value.toLowerCase().trim();
  }

  return TRUTHY_VALUES.some(function(t) {
    return t === value;
  });
}

getBoolean(false);   // false
getBoolean('false'); // false
getBoolean(1);       // true
getBoolean('true');  // true

七.測試一個數組內的==所有元素==是否都能通過某個指定函數的測試(every)

**every()** 方法測試一個數組內的所有元素是否都能通過某個指定函數的測試。它返回一個布爾值。

注意:若收到一個空數組,此方法在一切情況下都會返回 true

7.1 語法

arr.every(callback(element[, index[, array]])[, thisArg])

7.2 參數

  • callback

    用來測試每個元素的函數,它可以接收三個參數:element用于測試的當前值。index可選用于測試的當前值的索引。array可選調用 every 的當前數組。

  • thisArg

    執行 callback 時使用的 this 值。

7.3 返回值

如果回調函數的每一次返回都為 truthy 值,返回 **true** ,否則返回 **false**

7.4 描述

every 方法為數組中的每個元素執行一次 callback 函數,直到它找到一個會使 callback 返回 falsy 的元素。如果發現了一個這樣的元素,every 方法將會立即返回 false。否則,callback 為每一個元素返回 trueevery 就會返回 truecallback 只會為那些已經被賦值的索引調用。不會為那些被刪除或從未被賦值的索引調用。

callback 在被調用時可傳入三個參數:元素值,元素的索引,原數組。

如果為 every 提供一個 thisArg 參數,則該參數為調用 callback 時的 this 值。如果省略該參數,則 callback 被調用時的 this 值,在非嚴格模式下為全局對象,在嚴格模式下傳入 undefined。詳見 this 條目。

every 不會改變原數組。

every 遍歷的元素范圍在第一次調用 callback 之前就已確定了。在調用 every 之后添加到數組中的元素不會被 callback 訪問到。如果數組中存在的元素被更改,則他們傳入 callback 的值是 every 訪問到他們那一刻的值。那些被刪除的元素或從來未被賦值的元素將不會被訪問到。

every 和數學中的"所有"類似,當所有的元素都符合條件才會返回true。正因如此,若傳入一個空數組,無論如何都會返回 true。(這種情況屬于無條件正確:正因為一個空集合沒有元素,所以它其中的所有元素都符合給定的條件。)

7.5 案例

7.5.1檢測所有數組元素的大小

下例檢測數組中的所有元素是否都大于 10。

function isBigEnough(element, index, array) {
  return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough);   // false
[12, 54, 18, 130, 44].every(isBigEnough); // true

7.5.2 使用箭頭函數

箭頭函數為上面的檢測過程提供了更簡短的語法。

[12, 5, 8, 130, 44].every(x => x >= 10); // false
[12, 54, 18, 130, 44].every(x => x >= 10); // true

八.排序方法 sort

**sort()** 方法用原地算法對數組的元素進行排序,并返回數組。默認排序順序是在將元素轉換為字符串,然后比較它們的UTF-16代碼單元值序列時構建的

8.1 語法

arr.sort([compareFunction])

8.2 參數

  • compareFunction 可選

    用來指定按某種順序進行排列的函數。如果省略,元素按照轉換為的字符串的各個字符的Unicode位點進行排序。firstEl第一個用于比較的元素。secondEl第二個用于比較的元素。

8.3 返回值

排序后的數組。請注意,數組已原地排序,并且不進行復制。

8.4 描述

如果沒有指明 compareFunction ,那么元素會按照轉換為的字符串的諸個字符的Unicode位點進行排序。例如 "Banana" 會被排列到 "cherry" 之前。當數字按由小到大排序時,9 出現在 80 之前,但因為(沒有指明 compareFunction),比較的數字會先被轉換為字符串,所以在Unicode順序上 "80" 要比 "9" 要靠前。

如果指明了 compareFunction ,那么數組會按照調用該函數的返回值排序。即 a 和 b 是兩個將要被比較的元素:

  • 如果 compareFunction(a, b) 小于 0 ,那么 a 會被排列到 b 之前;

  • 如果 compareFunction(a, b) 等于 0 , a 和 b 的相對位置不變。備注: ECMAScript 標準并不保證這一行為,而且也不是所有瀏覽器都會遵守(例如 Mozilla 在 2003 年之前的版本);

  • 如果 compareFunction(a, b) 大于 0 , b 會被排列到 a 之前。

  • compareFunction(a, b) 必須總是對相同的輸入返回相同的比較結果,否則排序的結果將是不確定的。

所以,比較函數格式如下:

function compare(a, b) {
  if (a < b ) {           // 按某種排序標準進行比較, a 小于 b
    return -1;
  }
  if (a > b ) {
    return 1;
  }
  // a must be equal to b
  return 0;
}

要比較數字而非字符串,比較函數可以簡單的以 a 減 b,如下的函數將會將數組升序排列

function compareNumbers(a, b) {
  return a - b;
}

sort 方法可以使用 函數表達式 方便地書寫:

var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
  return a - b;
});
console.log(numbers);

也可以寫成:
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);

// [1, 2, 3, 4, 5]

對象可以按照某個屬性排序:

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic' },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return (a.value - b.value)
});

// sort by name
items.sort(function(a, b) {
  var nameA = a.name.toUpperCase(); // ignore upper and lowercase
  var nameB = b.name.toUpperCase(); // ignore upper and lowercase
  if (nameA < nameB) {
    return -1;
  }
  if (nameA > nameB) {
    return 1;
  }

  // names must be equal
  return 0;
});

8.5 案例

8.5.1.字母排序

sort默認的排序方式為字母排序,根據二十六個字母依次排列,單詞之間比較,則先比較第一個字母,如果第一個字母相同則比較第二個字母,以此類推。

  // 1.字母排序(sort默認排序)
   var arr = ["za","zb","a","b","xc","xa"];
   arr.sort();
   console.log(arr);
  // 運行結果:["a", "b", "xa", "xc", "za", "zb"]

8.5.2.sort數字排序

sort()中參數可以是方法函數,可以升序和降序輸出結果。

 //2.sort數字排序
  var array = [100,10,50,800,320,34,53];
    array.sort(function(a,b){
        //a-b升序,b-a降序
        return b-a;
    });
    console.log(array);
  //運行結果:[800, 320, 100, 53, 50, 34, 10]

注意:其中a,b都是表示這個數組里面的元素,如果是a-b則表示升序,如果是b-a則表示降序。

8.5.3.數組對象排序

最重要的還是這個對象屬性排序,當后臺給我們前端很多數據并且沒有排序時,我們一般都是要重新進行排序,而后臺給的數據往往是好幾層,不會像前面那種簡單的就一個數組,這個時候就要用sort中對象屬性排序了

  // 3.對象屬性排序
    var obj = [
        {name:"lucy", num:400},
        {name:"nancy", num:110},
        {name:"maria", num:200}
    ];
   obj.sort(compare("num"));
   console.log(obj);

   //數組對象屬性值排序
   function compare(property){
       return function(a,b){
           //value1 - value2升序
           //value2 - value1降序
           var value1 = a[property];
           var value2 = b[property];
           return value1 - value2;//升序
       }
   }
運行結果:
[
    {name:"nancy", num:110},
    {name:"maria", num:200},
    {name:"lucy", num:400}
]

注意:compare()中參數必須是這個對象的屬性名稱,而你要比較的這些對象里面,一定要有這個屬性名稱,否則會出錯。以上屬于個人總結,如果后期有什么補充會再次發布

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。