JavaScript30秒, 从入门到放弃之Array(四)

原文地点:
JavaScript30秒, 从入门到放弃之Array(四)

博客地点:JavaScript30秒, 从入门到放弃之Array(四)

程度有限,迎接批评指正

maxN

Returns the n maximum elements from the provided array. If n is greater than or equal to the provided array’s length, then return the original array(sorted in descending order).

Use Array.sort() combined with the spread operator (...) to create a shallow clone of the array and sort it in descending order. Use Array.slice() to get the specified number of elements. Omit the second argument, n, to get a one-element array.

const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);

返回一个数组的前n个最大值,假如指定的n大于或即是指定数组的长度,那末将返回原数组(按降序分列后)。

运用Array.sort()ES6的扩大运算符来天生一个按降序分列的浅度复制数组。运用Array.slice()来截取指定个数的数组元素。若省略第二个参数n时,n=1

➜  code cat maxN.js
const maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);

console.log(maxN([1, 2, 3]));
console.log(maxN([1, 2, 3], 2));

➜  code node maxN.js
[ 3 ]
[ 3, 2 ]

重要看懂这个sort就好了:

sort((a, b) => b - a)

这是降序排的要领,怎样讲?

变形一:

sort(fn(a,b))

这个fn呢有两个参数ab就是数组排序是按递次相邻的两个数组元素。a前、b后。

变形二:

sort((a, b) => {
  if (b > a) {
    return 1;
  } else if (b < a) {
    return -1;
  }
  return 0;
})

return1示意把前面的数a放背面,背面的数b在放前面;return0示意不换位置;return-1示意前面的数a放前面,背面的数b放背面。

例子中,当b > a时把a换到b背面,意即把大数放前边了,即降序分列。反之升序分列。

slice(0, n)

排完以后slice(0, n)截取前n个元素构成的数组即为数组最大的前n个数。

minN

Returns the n minimum elements from the provided array. If n is greater than or equal to the provided array’s length, then return the original array(sorted in ascending order).

Use Array.sort() combined with the spread operator (...) to create a shallow clone of the array and sort it in ascending order. Use Array.slice() to get the specified number of elements. Omit the second argument, n, to get a one-element array.

const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);

返回一个数组的前n个最小值,假如指定的n大于或即是指定数组的长度,那末将返回原数组(按升序分列后)。

运用Array.sort()ES6的扩大运算符来天生一个按升序分列的浅度复制数组。运用Array.slice()来截取指定个数的数组元素。若省略第二个参数n时,n=1

➜  code cat minN.js
const maxN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n);

console.log(maxN([1, 2, 3]));
console.log(maxN([1, 2, 3], 2));

➜  code node minN.js
[ 1 ]
[ 1, 2 ]

sort((a, b) => a - b)maxN相反,命题得证!

nthElement

Returns the nth element of an array.

Use Array.slice() to get an array containing the nth element at the first place. If the index is out of bounds, return []. Omit the second argument, n, to get the first element of the array.

const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];

返回指定数组的第n个元素(索引从0算起)。

运用Array.slice()截取数组,使截取的数组的第一个元素就是nth对应的元素。假如索引n凌驾数组局限,返回空数组[]。省略第二个参数n,按n=0计。

➜  code cat nthElement.js
const nthElement = (arr, n = 0) => (n > 0 ? arr.slice(n, n + 1) : arr.slice(n))[0];

console.log(nthElement(['a', 'b', 'c'], 1));
console.log(nthElement(['a', 'b', 'b'], -3));

➜  code node nthElement.js
b
a

就是简朴的用slice去截取元素,取截取后的第一个元素即可。

partition

Groups the elements into two arrays, depending on the provided function’s truthiness for each element.

Use Array.reduce() to create an array of two arrays. Use Array.push() to add elements for which fn returns true to the first array and elements for which fn returns false to the second one.

const partition = (arr, fn) =>
  arr.reduce(
    (acc, val, i, arr) => {
      acc[fn(val, i, arr) ? 0 : 1].push(val);
      return acc;
    },
    [[], []]
  );

依据供应的要领对一个数组就行挪用后,按运算效果的布尔值是不是为真分类。为真,归到二维数组索引为0的数组中;为假,归到二维数组索引为1的数组中。

运用Array.reduce()天生一个1x2的二维数组。运用Array.push()把指定fn运算效果为true的数组元素添加到二维数组的第一个数组中,运算效果为false的数组元素添加到二维数组的第二个数组中。

➜  code cat partition.js
const partition = (arr, fn) => arr.reduce((acc, val, i, arr) => {
    acc[fn(val, i, arr) ? 0 : 1].push(val);
    return acc;
}, [
    [],
    []
]);

const users = [{
    user: 'Pony',
    age: 47,
    active: true
}, {
    user: 'barney',
    age: 36,
    active: false
}, {
    user: 'fred',
    age: 40,
    active: true
}];

console.log(partition(users, o => o.active));

➜  code node partition.js
[ [ { user: 'Pony', age: 47, active: true },
    { user: 'fred', age: 40, active: true } ],
  [ { user: 'barney', age: 36, active: false } ] ]

acc的默认值是一个1x2的二维空数组[[], []]。跟着reduce的遍历历程将把满足对应前提的元素离别push到对应的数组中。

acc[fn(val, i, arr) ? 0 : 1].push(val);

fn(val, i, arr)假如为true将会把对应的元素val添加到acc的索引为0的数组中,不然添加到索引为1的数组中。如许遍历完毕就达到了分组的目标。

例子中,fno => o.active就是依据对象的active的属性是不是为true举行分类,所以我们看到,userPonyfred的元素都在二维数组的索引为0的数组中,其它在二维数组的索引为1的数组中。

pull

Mutates the original array to filter out the values specified.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in an array by resetting it’s length to zero and Array.push() to re-populate it with only the pulled values.

(For a snippet that does not mutate the original array see without)

const pull = (arr, ...args) => {
 let argState = Array.isArray(args[0]) ? args[0] : args;
 let pulled = arr.filter((v, i) => !argState.includes(v));
 arr.length = 0;
 pulled.forEach(v => arr.push(v));
};

转变原数组使其过滤掉指定的那些元素。

运用Array.filter()Array.includes()剔除数组里不需要的元素。先用Array.length = 0把原数组变成空数组,然后再经由过程Array.push()把过滤后盈余的元素从新添补进去。

(相似要领不转变原数组的请看without要领)

➜  code cat pull.js
const pull = (arr, ...args) => {
    let argState = Array.isArray(args[0]) ? args[0] : args;
    let pulled = arr.filter((v, i) => !argState.includes(v));
    arr.length = 0;
    pulled.forEach(v => arr.push(v));
};

let myArray = ['a', 'b', 'c', 'a', 'b', 'c'];
pull(myArray, 'a', 'c');
let secondArray = ['a', 'b', 'c', 'a', 'b', 'c'];
pull(secondArray, ['a', 'c'], 'b');

console.log(myArray);
console.log(secondArray);

➜  code node pull.js
args:  [ 'a', 'c' ]
args:  [ [ 'a', 'b' ], 'c' ]
[ 'b', 'b' ]
[ 'c', 'c' ]
let argState = Array.isArray(args[0]) ? args[0] : args;

推断args的第一个元素是不是是一个数组,假如是,把该数组赋值给argState作为后续消除数组元素的元数组;不然args就是元数组。

let pulled = arr.filter((v, i) => !argState.includes(v));

连系filterincludes把数组arr中包括在argState中的元素消撤除。

arr.length = 0;
pulled.forEach(v => arr.push(v));

此处,把数组长度设为0,将数组置空,然后再遍历pulled,把一切pulled的元素pusharr中,终究arr就只含有消撤除指定元素后的其他元素。

pullAtIndex

Mutates the original array to filter out the values at the specified indexes.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in an array by resetting it’s length to zero and Array.push() to re-populate it with only the pulled values. Use Array.push() to keep track of pulled values

const pullAtIndex = (arr, pullArr) => {
 let removed = [];
 let pulled = arr
   .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
   .filter((v, i) => !pullArr.includes(i));
 arr.length = 0;
 pulled.forEach(v => arr.push(v));
 return removed;
};

转变原数组使其过滤掉指定的那些索引值对应的元素。

运用Array.filter()Array.includes()剔除数组里不需要的元素。先用Array.length = 0把原数组变成空数组,然后再经由过程Array.push()把过滤后盈余的元素从新添补进去。同时运用Array.push()跟踪纪录剔撤除的一切元素。

➜  code cat pullAtIndex.js
const pullAtIndex = (arr, pullArr) => {
    let removed = [];
    let pulled = arr.map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
        .filter((v, i) => !pullArr.includes(i));

    arr.length = 0;
    pulled.forEach((v) => arr.push(v));
    return removed;
};

let myArray = ['a', 'b', 'c', 'd'];
let pulled = pullAtIndex(myArray, [1, 3]);

console.log('myArray: ', myArray);
console.log('pulled: ', pulled);

➜  code node pullAtIndex.js
myArray:  [ 'a', 'c' ]
pulled:  [ 'b', 'd' ]
let pulled = arr
  .map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))
  .filter((v, i) => !pullArr.includes(i));

arrmap是为了把要消撤除的元素pushremoved变量中。pullArr.includes(i) ? removed.push(v) : v这个三元运算符就是推断索引是不是在要消撤除的指定索引数组pullArr中。假如在,添加到removed中,不然直接返回该元素。

接下来filterarr中婚配pullArr的索引对应元素剔撤除。

arr.length = 0;
pulled.forEach((v) => arr.push(v));
return removed;

末了把arr置空后再填入满足前提的元素,然后返回剔撤除的元素构成的数组。

pullAtValue

Mutates the original array to filter out the values specified. Returns the removed elements.

Use Array.filter() and Array.includes() to pull out the values that are not needed. Use Array.length = 0 to mutate the passed in an array by resetting it’s length to zero and Array.push() to re-populate it with only the pulled values. Use Array.push() to keep track of pulled values

const pullAtValue = (arr, pullArr) => {
  let removed = [],
    pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)),
    mutateTo = arr.filter((v, i) => !pullArr.includes(v));
  arr.length = 0;
  mutateTo.forEach(v => arr.push(v));
  return removed;
};

转变原数组使其过滤掉指定的那些值所婚配的元素们,返回剔撤除一切元素构成的数组。

运用Array.filter()Array.includes()剔除数组里不需要的元素。先用Array.length = 0把原数组变成空数组,然后再经由过程Array.push()把过滤后盈余的元素从新添补进去。同时运用Array.push()跟踪纪录剔撤除的一切元素。

➜  code cat pullAtValue.js
const pullAtValue = (arr, pullArr) => {
    let removed = [],
        pushToRemove = arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v)),
        mutateTo = arr.filter((v, i) => !pullArr.includes(v));

    arr.length = 0;
    mutateTo.forEach((v) => arr.push(v));
    return removed;
};

let myArray = ['a', 'b', 'c', 'd'];
let pulled = pullAtValue(myArray, ['b', 'd']);

console.log('myArray: ', myArray);
console.log('pulled: ', pulled);

➜  code node pullAtValue.js
myArray:  [ 'a', 'c' ]
pulled:  [ 'b', 'd' ]

逻辑上和pullAtIndex差不多,差异就在一个是过滤索引,另一个是过滤

为此完成上就有了以下差别:

// pullAtIndex
arr.map((v, i) => (pullArr.includes(i) ? removed.push(v) : v))

// pullAtValue
arr.forEach((v, i) => (pullArr.includes(v) ? removed.push(v) : v))

一个用了arr.map,一个用了arr.forEach

为何呢?

arr.maparr的元素是会转变的,然则关于要剔撤除索引来讲要删撤除索引对应的值是不是有变化是可有可无的。而关于婚配值来讲就不灵了,由于原本要剔撤除的值在map的历程当中转变了,到filter的时刻就婚配不出来了,就没法剔除了。

所以改成了arr.forEach,它是不转变数组元素的,没有副作用,不滋扰后续filter。别的forEach的效果是undefined

reducedFilter

Filter an array of objects based on a condition while also filtering out unspecified keys.

Use Array.filter() to filter the array based on the predicate fn so that it returns the objects for which the condition returned a truthy value. On the filtered array, use Array.map() to return the new object using Array.reduce() to filter out the keys which were not supplied as the keys argument.

const reducedFilter = (data, keys, fn) =>
  data.filter(fn).map(el =>
    keys.reduce((acc, key) => {
      acc[key] = el[key];
      return acc;
    }, {})
  );

依据一个前提对一个数组举行过滤,同时过滤掉不需要的键。

运用Array.filter()去过滤出指定要领fn对数组元素对象挪用效果为真值的元素,对过滤后的数组运用Array.map()返回一个新的对象,对象包括的键值对是由Array.reduce()依据指定keys过滤掉不需要的键而构成的。

➜  code cat reducedFilter.js
const reducedFilter = (data, keys, fn) =>
    data.filter(fn).map(el =>
        keys.reduce((acc, key) => {
            acc[key] = el[key];
            return acc;
        }, {})
    );


const data = [{
    id: 1,
    name: 'john',
    age: 24
}, {
    id: 2,
    name: 'mike',
    age: 50
}];

console.log(reducedFilter(data, ['id', 'name'], item => item.age > 24));

➜  code node reducedFilter.js
[ { id: 2, name: 'mike' } ]
data.filter(fn)

数组data依据要领fn过滤掉了不满足前提的数组元素。

keys.reduce((acc, key) => {
  acc[key] = el[key];
  return acc;
}, {})

keys是终究要保存的键的数组,reduceacc初始值是空对象{},遍历历程当中,把一切的el对象中键包括于keys数组一切键值对累加到acc对象中。

map(el => fn1)

末了团结map要领能够看出,终究返回的是一个数组,数组内包括fn1要领也就是keys.reduce要领返回的acc的对象。

remove

Removes elements from an array for which the given function returns false.

Use Array.filter() to find array elements that return truthy values and Array.reduce() to remove elements using Array.splice(). The func is invoked with three arguments (value, index, array).

const remove = (arr, func) =>
  Array.isArray(arr)
    ? arr.filter(func).reduce((acc, val) => {
        arr.splice(arr.indexOf(val), 1);
        return acc.concat(val);
      }, [])
    : [];

删除数组中以指定要领挪用效果为false的一切元素。

运用Array.filter()来找出数组中一切运转指定要领效果为真的元素,运用Array.reduce()合营Array.splice()删撤除不需要的元素。func函数挪用有三个参数(value, index, array)

➜  code cat remove.js
const remove = (arr, func) =>
    Array.isArray(arr) ?
    arr.filter(func).reduce((acc, val) => {
        arr.splice(arr.indexOf(val), 1);
        return acc.concat(val);
    }, []) : [];

const arr = [1,2,3,4];
console.log(remove(arr, n => n % 2 == 0));
console.log(arr);

➜  code node remove.js
[ 2, 4 ]
[ 1, 3 ]
Array.isArray(arr) ? filterfun : [];

先推断给定参数arr是不是是一个数组,是,实行filter函数;否,直接返回效果空数组[]

arr.filter(func).reduce((acc, val) => {
  arr.splice(arr.indexOf(val), 1);
  return acc.concat(val);
}, [])

arr.filter(func)起首过滤出func运转效果为真一切数组元素。reduce要领将filter盈余的一切数组元素以concat的体式格局返回效果数组。而在原数组arr中,则用splicefunc运转效果为真的一切元素剔除。

实在就终究的返回效果来讲,arr.filter(func)已能够返回准确的效果,之所以看起来节外生枝的运用了reduce的缘由在于必需把不需要的元素从原数组arr中剔除。

以下是我在没看代码之前依据例子运转效果先写的代码:

➜  code cat remove1.js
const remove = (arr, fn) => {
  let removed = [];
  arr.forEach(v => (fn(v) ? removed.push(v) : v));
  const left = arr.filter(v => !fn(v));

  arr.length = 0;
  left.forEach(v => arr.push(v));

  return removed;
};

const arr = [1,2,3,4];
console.log(remove(arr, n => n % 2 == 0));
console.log(arr);

➜  code node remove1.js
[ 2, 4 ]
[ 1, 3 ]

我以为代码自身应当没什么题目,但能够没那末文雅,别的就是没有做Array.isArray的前置前提推断。

sample

Returns a random element from an array.

Use Math.random() to generate a random number, multiply it by length and round it of to the nearest whole number using Math.floor(). This method also works with strings.

const sample = arr => arr[Math.floor(Math.random() * arr.length)];

返回数组中随机的一个元素。

运用Math.random()天生一个随机数,乘以数组的长度,然后再配以Math.floor()猎取整数索引,进而返回该索引对应的数组元素。这个要领也一样适用于字符串。

            ➜  code cat sample.js
const sample = (arr) => arr[Math.floor(Math.random() * arr.length)]

console.log(sample([3, 7, 9, 11]));

➜  code node sample.js
7
    原文作者:supermao
    原文地址: https://segmentfault.com/a/1190000012919519
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞