原文地址:JavaScript30秒, 从入门到放弃之Array(四)javascript
博客地址:JavaScript30秒, 从入门到放弃之Array(四)java
水平有限,欢迎批评指正node
Returns the
n
maximum elements from the provided array. Ifn
is greater than or equal to the provided array's length, then return the original array(sorted in descending order).gitUse
Array.sort()
combined with the spread operator (...
) to create a shallow clone of the array and sort it in descending order. UseArray.slice()
to get the specified number of elements. Omit the second argument,n
, to get a one-element array.githubconst maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n); 复制代码
返回一个数组的前n个最大值,若是指定的n
大于或等于指定数组的长度,那么将返回原数组(按降序排列后)。数组
使用Array.sort()
和ES6
的扩展运算符…
来生成一个按降序排列的浅度复制数组。使用Array.slice()
来截取指定个数的数组元素。若省略第二个参数n
时,n=1
。bash
➜ 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
就行了:dom
sort((a, b) => b - a)
复制代码
这是降序排的方法,怎么讲?ide
变形一:函数
sort(fn(a,b))
复制代码
这个fn
呢有两个参数a
、b
就是数组排序是按顺序相邻的两个数组元素。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
个数。
Returns the
n
minimum elements from the provided array. Ifn
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. UseArray.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
相反,命题得证!
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
去截取元素,取截取后的第一个元素便可。
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. UseArray.push()
to add elements for whichfn
returnstrue
to the first array and elements for whichfn
returnsfalse
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
的数组中。这样遍历结束就达到了分组的目的。
例子中,fn
是o => o.active
就是根据对象的active
的属性是否为true
进行分类,因此咱们看到,user
为Pony
和fred
的元素都在二维数组的索引为0的数组中,其它在二维数组的索引为1的数组中。
Mutates the original array to filter out the values specified.
Use
Array.filter()
andArray.includes()
to pull out the values that are not needed. UseArray.length = 0
to mutate the passed in an array by resetting it's length to zero andArray.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));
复制代码
结合filter
和includes
把数组arr
中包含在argState
中的元素排除掉。
arr.length = 0;
pulled.forEach(v => arr.push(v));
复制代码
此处,把数组长度设为0,将数组置空,而后再遍历pulled
,把全部pulled
的元素push
到arr
中,最终arr
就只含有排除掉指定元素后的其余元素。
Mutates the original array to filter out the values at the specified indexes.
Use
Array.filter()
andArray.includes()
to pull out the values that are not needed. UseArray.length = 0
to mutate the passed in an array by resetting it's length to zero andArray.push()
to re-populate it with only the pulled values. UseArray.push()
to keep track of pulled valuesconst 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));
复制代码
arr
先map
是为了把要排除掉的元素push
到removed
变量中。pullArr.includes(i) ? removed.push(v) : v
这个三元运算符就是判断索引是否在要排除掉的指定索引数组pullArr
中。若是在,添加到removed
中,不然直接返回该元素。
接下来filter
把arr
中匹配pullArr
的索引对应元素剔除掉。
arr.length = 0;
pulled.forEach((v) => arr.push(v));
return removed;
复制代码
最后把arr
置空后再填入知足条件的元素,而后返回剔除掉的元素组成的数组。
Mutates the original array to filter out the values specified. Returns the removed elements.
Use
Array.filter()
andArray.includes()
to pull out the values that are not needed. UseArray.length = 0
to mutate the passed in an array by resetting it's length to zero andArray.push()
to re-populate it with only the pulled values. UseArray.push()
to keep track of pulled valuesconst 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.map
后arr
的元素是会改变的,可是对于要剔除掉索引来讲要删除掉索引对应的值是否有变化是可有可无的。而对于匹配值来讲就不灵了,由于原本要剔除掉的值在map
的过程当中改变了,到filter
的时候就匹配不出来了,就没法剔除了。
因此改为了arr.forEach
,它是不改变数组元素的,没有反作用,不干扰后续filter
。另外forEach
的结果是undefined
。
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 predicatefn
so that it returns the objects for which the condition returned a truthy value. On the filtered array, useArray.map()
to return the new object usingArray.reduce()
to filter out the keys which were not supplied as thekeys
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
是最终要保留的键的数组,reduce
的acc
初始值是空对象{}
,遍历过程当中,把全部的el
对象中键包含于keys
数组全部键值对累加到acc
对象中。
map(el => fn1)
复制代码
最后联合map
方法能够看出,最终返回的是一个数组,数组内包含fn1
方法也就是keys.reduce
方法返回的acc
的对象。
Removes elements from an array for which the given function returns
false
.Use
Array.filter()
to find array elements that return truthy values andArray.reduce()
to remove elements usingArray.splice()
. Thefunc
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
中,则用splice
将func
运行结果为真的全部元素剔除。
其实就最终的返回结果来讲,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
的前置条件判断。
Returns a random element from an array.
Use
Math.random()
to generate a random number, multiply it bylength
and round it of to the nearest whole number usingMath.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
复制代码