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()中参数必须是这个对象的属性名称,而你要比较的这些对象里面,一定要有这个属性名称,否则会出错。以上属于个人总结,如果后期有什么补充会再次发布

你可能感兴趣的:(01.数组的高级方法)