原文地址: JavaScript30秒, 從入門到放棄之Array(四)博客地址:JavaScript30秒, 從入門到放棄之Array(四)javascript
水平有限,歡迎批評指正java
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).nodeUse
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.gitconst maxN = (arr, n = 1) => [...arr].sort((a, b) => b - a).slice(0, n);
返回一個數組的前n個最大值,若是指定的n
大於或等於指定數組的長度,那麼將返回原數組(按降序排列後)。github
使用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
就行了:dom
sort((a, b) => b - a)
這是降序排的方法,怎麼講?ide
變形一:函數
sort(fn(a,b))
這個fn
呢有兩個參數a
、b
就是數組排序是按順序相鄰的兩個數組元素。a
前、b
後。rest
變形二:
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