摘要:原文地址秒,從入門到放棄之五博客地址秒,從入門到放棄之五水平有限,歡迎批評指正從給定的數(shù)組中隨機(jī)選出指定個數(shù)的數(shù)組元素。否則判斷數(shù)組元素是否大于或者等于指定元素,尋找過程與前邊類似。
原文地址:JavaScript30秒, 從入門到放棄之Array(五)sampleSize博客地址:JavaScript30秒, 從入門到放棄之Array(五)
水平有限,歡迎批評指正
Gets n random elements at unique keys from array up to the size of array.
Shuffle the array using the Fisher-Yates algorithm. Use Array.slice() to get the first n elements. Omit the second argument, n to get only one element at random from the array.
const sampleSize = ([...arr], n = 1) => { let m = arr.length; while (m) { const i = Math.floor(Math.random() * m--); [arr[m], arr[i]] = [arr[i], arr[m]]; } return arr.slice(0, n); };
從給定的數(shù)組中隨機(jī)選出指定個數(shù)的數(shù)組元素。
用 Fisher-Yates 算法將數(shù)組洗牌(打亂順序)。然后使用Array.slice() 來截取數(shù)組的前n個元素。如果省略第二個參數(shù)n,按n=1處理,即僅取一個隨機(jī)元素。
? code cat sampleSize.js const sampleSize = ([...arr], n = 1) => { let m = arr.length; while (m) { const i = Math.floor(Math.random() * m--); [arr[m], arr[i]] = [arr[i], arr[m]]; } return arr.slice(0, n); }; console.log(sampleSize([1, 2, 3], 2)); console.log(sampleSize([1, 2, 3], 4)); ? code node sampleSize.js [ 2, 1 ] [ 1, 3, 2 ]
let m = arr.length; while (m) { const i = Math.floor(Math.random() * m--); [arr[m], arr[i]] = [arr[i], arr[m]]; }
關(guān)鍵點是這個while循環(huán),按數(shù)組初始長度m每次遞減1循環(huán),然后結(jié)合Math.floor和Math.random在m范圍內(nèi)生成一個隨機(jī)索引。用該索引對應(yīng)的數(shù)組元素與索引m-1(即未交換過的最后一個元素)對應(yīng)數(shù)組元素交換位置。循環(huán)結(jié)束,數(shù)組洗牌成功。
return arr.slice(0, n);
最后返回被截取的前n個元素。
shuffleRandomizes the order of the values of an array, returning a new array.
Uses the Fisher-Yates algorithm to reorder the elements of the array.
const shuffle = ([...arr]) => { let m = arr.length; while (m) { const i = Math.floor(Math.random() * m--); [arr[m], arr[i]] = [arr[i], arr[m]]; } return arr; };
對指定數(shù)組進(jìn)行隨機(jī)排序并返回排好序的新數(shù)組。
用 Fisher-Yates 算法將數(shù)組洗牌(打亂順序)并返回排好序的新數(shù)組。
? code cat shuffle.js const shuffle = ([...arr]) => { let m = arr.length; while (m) { const i = Math.floor(Math.random() * m--); [arr[m], arr[i]] = [arr[i], arr[m]]; } return arr; }; const foo = [1, 2, 3]; console.log(shuffle(foo)); console.log(foo); ? code node shuffle.js [ 1, 3, 2 ] [ 1, 2, 3 ]
這就是前面sampleSize用到的算法,注意的是返回的是新的數(shù)組,不是在原數(shù)組上進(jìn)行排序的。
similarityReturns an array of elements that appear in both arrays.
Use Array.filter() to remove values that are not part of values, determined using Array.includes().
const similarity = (arr, values) => arr.filter(v => values.includes(v));
返回一個包含兩個數(shù)組的共同元素的數(shù)組。
使用Array.filter()結(jié)合Array.includes()把一個數(shù)組中不屬于第二個數(shù)組values的元素都剔除。
? code cat similarity.js const similarity = (arr, values) => arr.filter(v => values.includes(v)); console.log(similarity([1, 2, 3], [1, 2, 4])); ? code node similarity.js [ 1, 2 ]
filter的主體是第一個數(shù)組arr,最終將不滿足條件的元素剔除掉。那么不滿足的條件又是什么呢?
v => values.includes(v)
條件是第一個數(shù)組arr不在第二個數(shù)組values里的所有元素,也即僅保留滿足values.includes(v)的所有元素。
sortedIndexReturns the lowest index at which value should be inserted into array in order to maintain its sort order.
Check if the array is sorted in descending order (loosely). Use Array.findIndex() to find the appropriate index where the element should be inserted.
const sortedIndex = (arr, n) => { const isDescending = arr[0] > arr[arr.length - 1]; const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); return index === -1 ? arr.length : index; };
返回一個元素應(yīng)該插入到已知排好序的數(shù)組并且不改變該數(shù)組排序方式的最小索引。
檢查一個數(shù)組是否已經(jīng)按降序排列(松散的),然后使用Array.findIndex()去找出指定的元素應(yīng)該插在數(shù)組中合適位置的索引并返回。
? code cat sortedIndex.js const sortedIndex = (arr, n) => { const isDescending = arr[0] > arr[arr.length - 1]; const index = arr.findIndex(el => (isDescending ? n >= el : n <= el)); return index === -1 ? arr.length : index; }; console.log(sortedIndex([5, 3, 2, 1], 4)); console.log(sortedIndex([30, 50], 40)); ? code node sortedIndex.js 1 1
之所以叫sortedIndex是因為數(shù)組已經(jīng)排序了,但升序降序未知。為此只需比較數(shù)組第一個元素arr[0]和數(shù)組最后一個元素arr[arr.length - 1]的大小即可判斷升降序。
const index = arr.findIndex(el => (isDescending ? n >= el : n <= el));
這里有一個三元運算表達(dá)式:
isDescending ? n >= el : n <= el
如果是降序的,判斷數(shù)組arr元素el是否小于或者等于指定元素n,也就是說,當(dāng)滿足指定數(shù)組元素n首次大于或者等于arr遍歷過程中任意一個元素el的時候,就返回此時的索引。否則判斷數(shù)組arr元素el是否大于或者等于指定元素n,尋找過程與前邊類似。
return index === -1 ? arr.length : index;
最后,判斷所找索引index是否為-1,若是,說明n比arr所有元素要小,應(yīng)該放在arr最后一位,即index = arr.length;否則直接返回索引index。
sortedIndexByReturns the lowest index at which value should be inserted into array in order to maintain its sort order, based on a provided iterator function.
Check if the array is sorted in descending order (loosely). Use Array.findIndex() to find the appropriate index where the element should be inserted, based on the iterator function fn.
const sortedIndexBy = (arr, n, fn) => { const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); const val = fn(n); const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); return index === -1 ? arr.length : index; };
返回一個元素應(yīng)該插入到已知排好序的數(shù)組并且不改變該數(shù)組排序方式的最小索引,前提是受一個指定的方法支配。
檢查一個數(shù)組是否已經(jīng)按降序排列(松散的),然后使用Array.findIndex()去找出指定的元素應(yīng)該插在數(shù)組中合適位置的索引并返回,前提是受一個指定的方法支配。
? code cat sortedIndexBy.js const sortedIndexBy = (arr, n, fn) => { const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); const val = fn(n); const index = arr.findIndex(el => (isDescending ? val >= fn(el) : val <= fn(el))); return index === -1 ? arr.length : index; }; console.log(sortedIndexBy([{ x: 3 }, { x: 4 }, { x: 5 }], { x: 4 }, o => o.x)); ? code node sortedIndexBy.js 1
sortedIndexBy跟sortedIndex字面上只差一個By,一般而言By有基于xx的意思。
這里就是基于某個方法fn,意即在findIndex找合適元素的時候指的是對元素調(diào)用fn后的結(jié)果來進(jìn)行比較,而不是元素本身。另外要注意的是,判斷原數(shù)組arr升降序是也是fn調(diào)用結(jié)果的升降序,而不是元素本身的升降序。
sortedLastIndexReturns the highest index at which value should be inserted into array in order to maintain its sort order.
Check if the array is sorted in descending order (loosely). Use Array.map() to map each element to an array with its index and value. Use Array.reverse() and Array.findIndex() to find the appropriate last index where the element should be inserted.
const sortedLastIndex = (arr, n) => { const isDescending = arr[0] > arr[arr.length - 1]; const index = arr .map((val, i) => [i, val]) .reverse() .findIndex(el => (isDescending ? n <= el[1] : n >= el[1])); return index === -1 ? 0 : arr.length - index - 1; };
返回一個元素應(yīng)該插入到已知排好序的數(shù)組并且不改變該數(shù)組排序方式的最大索引(從右邊數(shù)的最小索引)。
檢查一個數(shù)組是否已經(jīng)按降序排列(松散的),然后使用Array.map()把原數(shù)組map一個包含索引和元素值的二維數(shù)組,在此map后的數(shù)組上用Array.findIndex()去找出指定的元素應(yīng)該插在數(shù)組從右邊數(shù)的合適位置的索引并返回。
? code cat sortedLastIndex.js const sortedLastIndex = (arr, n) => { const isDescending = arr[0] > arr[arr.length - 1]; const index = arr .map((v, i) => [i, v]) .reverse() .findIndex(el => (isDescending ? n <= el[1] : n >= el[1])); return index === -1 ? 0 : arr.length - index; }; console.log(sortedLastIndex([10, 20, 30, 30, 40], 30)); ? code node sortedLastIndex.js 4
const index = arr .map((v, i) => [i, v]) .reverse() .findIndex(el => (isDescending ? n <= el[1] : n >= el[1]));
首先用原數(shù)組arr去map一個二維數(shù)組,至于為什么一定要去map待會再講。
然后reverse()去把map后的二維數(shù)組翻轉(zhuǎn)。
最后在翻轉(zhuǎn)數(shù)組基礎(chǔ)上去查找對應(yīng)索引:
// sortedLastIndex isDescending ? n <= el[1] : n >= el[1] // sortedIndex isDescending ? n >= el : n <= el
這里不難看出sortedLastIndex和sortedIndex的三元運算表達(dá)式是不一樣的。
sortedLastIndex此時是對一個二維數(shù)組進(jìn)行findIndex查找,二維數(shù)組的第二個元素即el[1]才是值,所以要跟它比較。
sortedLastIndex的二維數(shù)組是經(jīng)過翻轉(zhuǎn)的,即如果本來數(shù)組是降序的,翻轉(zhuǎn)后為升序,所以應(yīng)該找元素n首次滿足小于或等于數(shù)組元素el[1]的索引,而sortedIndex顯然相反。
最終再對找出來的是索引index進(jìn)行判斷,如果index === -1,那么應(yīng)該返回0,怎么講?
對于-1來說,從右邊數(shù)起,把整個數(shù)組數(shù)完了,都沒有找到能放它的位置,那么只有數(shù)組第一個位置符合它。
如果index !== -1,也就是找到一個合適的索引,但是這個index是從右邊數(shù)的,轉(zhuǎn)換成從左邊數(shù)的索引就是arr.length - index,(原文是arr.length - index - 1)我認(rèn)為是錯的。舉個例子:
arr = [5, 4, 3, 3, 2, 1] 要把3插入數(shù)組arr的從右邊數(shù)是2; 從左邊數(shù)是4,即是:6 - 2 = 4
接著前面說的為什么一定需要map,map是返回一個新的數(shù)組而不改變原數(shù)組,arr.reverse()是會直接改變原數(shù)組arr的,arr.map(fn).reverse()則不會改變arr而只是改變了arr.map(fn)后返回的數(shù)組。
然而我個人覺得map的時候沒必要返回一個二維數(shù)組,直接一維數(shù)組就可以了,因為后續(xù)根本用不到map后的第一個元素el[0]即它對應(yīng)的索引。
如:
? code cat sortedLastIndexSave.js const sortedLastIndex = (arr, n) => { const isDescending = arr[0] > arr[arr.length - 1]; const index = arr .map(v => v) .reverse() .findIndex(el => (isDescending ? n <= el : n >= el)); return index === -1 ? 0 : arr.length - index - 1; }; const arr = [10, 20, 30, 30, 40]; console.log(sortedLastIndex(arr, 30)); console.log(arr); ? code node sortedLastIndexSave.js 3 [ 10, 20, 30, 30, 40 ]
結(jié)果一樣,并且原數(shù)組arr并未改變。
sortedLastIndexByReturns the highest index at which value should be inserted into array in order to maintain its sort order, based on a provided iterator function.
Check if the array is sorted in descending order (loosely). Use Array.reverse() and Array.findIndex() to find the appropriate last index where the element should be inserted, based on the iterator function fn..
const sortedLastIndexBy = (arr, n, fn) => { const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); const val = fn(n); const index = arr .map((val, i) => [i, fn(val)]) .reverse() .findIndex(el => (isDescending ? val <= el[1] : val >= el[1])); return index === -1 ? 0 : arr.length - index; };
返回一個元素應(yīng)該插入到已知排好序的數(shù)組并且不改變該數(shù)組排序方式的最大索引(從右邊數(shù)的最小索引),前提是受一個指定的方法支配。
檢查一個數(shù)組是否已經(jīng)按降序排列(松散的),然后使用Array.reverse()和Array.findIndex()去找出指定的元素應(yīng)該插在數(shù)組從右邊數(shù)的合適位置的索引并返回,前提是受一個指定的方法支配。
? code cat sortedLastIndexBy.js const sortedLastIndexBy = (arr, n, fn) => { const isDescending = fn(arr[0]) > fn(arr[arr.length - 1]); const val = fn(n); const index = arr .map((val, i) => [i, fn(val)]) .reverse() .findIndex(el => (isDescending ? val <= el[1] : val >= el[1])); return index === -1 ? 0 : arr.length - index; }; console.log(sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x)); console.log(sortedLastIndexBy([{ x: 40 }, { x: 30 }, { x: 30 }, { x: 20 }, { x: 10 }], { x: 30 }, o => o.x)); console.log(sortedLastIndexBy([{ x: 10 }, { x: 20 }, { x: 30 }, { x: 30 }, { x: 40 }], { x: 30 }, o => o.x)); ? code node sortedLastIndexBy.js 1 3 4
這個跟前面的sortedLastIndex差別其實就是是否調(diào)用fn后再比較的問題,沒啥可說的了。
symmetricDifferenceReturns the symmetric difference between two arrays.
Create a Set from each array, then use Array.filter() on each of them to only keep values not contained in the other.
const symmetricDifference = (a, b) => { const sA = new Set(a), sB = new Set(b); return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; };
返回兩個數(shù)組中對稱不相同的元素(簡單說就是數(shù)組a中不存在于數(shù)組b中的所有元素加上數(shù)組b中不存在于數(shù)組a中的所有元素)。
對兩個數(shù)組分別創(chuàng)建其集合。然后分別使用Array.filter()過濾出不存在于對方的所有元素。
? code cat symmetricDifference.js const symmetricDifference = (a, b) => { const sA = new Set(a), sB = new Set(b); return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))]; }; console.log(symmetricDifference([1, 2, 3], [1, 2, 4])); ? code node symmetricDifference.js [ 3, 4 ]
其實前面的解釋就已經(jīng)很清楚了。主要看return那行:
return [...a.filter(x => !sB.has(x)), ...b.filter(x => !sA.has(x))];
a.filter(x => !sB.has(x))這里保留a數(shù)組里所有不在b數(shù)組的集合里的元素,加上…展開運算符把這些元素拼接成數(shù)組,同理,對b數(shù)組也一樣。
symmetricDifferenceByReturns the symmetric difference between two arrays, after applying the provided function to each array element of both.
Create a Set by applying fn to each array"s elements, then use Array.filter() on each of them to only keep values not contained in the other.
const symmetricDifferenceBy = (a, b, fn) => { const sA = new Set(a.map(v => fn(v))), sB = new Set(b.map(v => fn(v))); return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; };
返回兩個數(shù)組中對稱不相同的元素,前提是對兩個數(shù)組所有元素調(diào)用指定方法后。(簡單說就是數(shù)組a中不存在于數(shù)組b中的所有元素加上數(shù)組b中不存在于數(shù)組a中的所有元素,前提是調(diào)用指定方法后)。
對兩個數(shù)組分別調(diào)用指定方法后創(chuàng)建其集合。然后分別使用Array.filter()過濾出不存在于對方的
? code cat symmetricDifferenceBy.js const symmetricDifferenceBy = (a, b, fn) => { const sA = new Set(a.map(v => fn(v))), sB = new Set(b.map(v => fn(v))); return [...a.filter(x => !sB.has(fn(x))), ...b.filter(x => !sA.has(fn(x)))]; }; console.log(symmetricDifferenceBy([2.1, 1.2], [2.3, 3.4], Math.floor)); ? code node symmetricDifferenceBy.js [ 1.2, 3.4 ]
跟symmetricDifference的不同點在于多了一個fn,所以在創(chuàng)建集合之前,要先對數(shù)組元素map一個對所有元素運用fn的方法。再各自過濾的時候也同樣使用fn對數(shù)組元素進(jìn)行調(diào)用。
symmetricDifferenceWithReturns the symmetric difference between two arrays, using a provided function as a comparator.
Use Array.filter() and Array.findIndex() to find the appropriate values.
const symmetricDifferenceWith = (arr, val, comp) => [ ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1) ];
返回兩個數(shù)組中對稱不相同的元素,前提是使用一個指定的比較方法進(jìn)行比較。
使用Array.filter()和Array.findIndex()來找出符合條件的所有元素。
? code cat symmetricDifferenceWith.js const symmetricDifferenceWith = (arr, val, comp) => [ ...arr.filter(a => val.findIndex(b => comp(a, b)) === -1), ...val.filter(a => arr.findIndex(b => comp(a, b)) === -1), ]; const res = symmetricDifferenceWith( [1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b) ); console.log(res); ? code node symmetricDifferenceWith.js [ 1, 1.2, 3.9 ]
這個就是對數(shù)組arr,過濾出對數(shù)組arr和val所有元素調(diào)用comp方法后結(jié)果不同的所有元素。同理對數(shù)組val也一樣。然后兩者的結(jié)果拼接成最終的結(jié)果。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107379.html
摘要:循環(huán)一個數(shù)組,使用每次去刪除該數(shù)組的第一個元素直到指定方法運算結(jié)果為,返回的是剩余元素組成的數(shù)組。直到循環(huán)退出,返回此時的。對應(yīng)就是,包含下界,不包含上屆。秒,從入門到放棄之二微信公眾號秒,從入門到放棄之二 difference Returns the difference between two arrays. Create a Set from b, then use Array...
摘要:否則,直接循環(huán)去拼接該值返回按照指定的方法對數(shù)組元素進(jìn)行分組歸類。使用創(chuàng)建一個對象,對象的鍵是生成的結(jié)果,值是符合該鍵的所有數(shù)組元素組成的數(shù)組。微信公眾號秒,從入門到放棄之三 原文鏈接:JavaScript30秒, 從入門到放棄之Array(三)水平有限,歡迎批評指正 flattenDepth Flattens an array up to the specified depth....
摘要:從數(shù)組索引為開始刪除元素,直到對數(shù)組元素運用指定方法為為止。對兩個數(shù)組的元素分別調(diào)用指定方法后,返回以運行結(jié)果為判定基準(zhǔn)的并集,并集是原始數(shù)組元素的并集而不是運行結(jié)果的并集。 原文地址:JavaScript30秒, 從入門到放棄之Array(六)博客地址:JavaScript30秒, 從入門到放棄之Array(六) 水平有限,歡迎批評指正 tail Returns all elem...
摘要:地址秒,從入門到放棄之七博客地址秒,從入門到放棄之七水平有限,歡迎批評指正剔除掉數(shù)組中所有存在于所指定的元素們的項。使用,和來創(chuàng)建由兩個數(shù)組元素拼接而成的所有可能對并將它們存在一個數(shù)組中的數(shù)組。 GitHub地址:JavaScript30秒, 從入門到放棄之Array(七)博客地址:JavaScript30秒, 從入門到放棄之Array(七) 水平有限,歡迎批評指正 without ...
摘要:三元運算符遍歷過程中判斷遍歷數(shù)組值是否嚴(yán)格等于指定值,是,次數(shù)否,。三元運算符判斷是否是一個數(shù)組,是,返回遞歸運用后的值否,直接返回。秒,從入門到放棄博客地址秒,從入門到放棄微信公眾號地址秒,從入門到放棄 有意思 最近很火的github上的庫30-seconds-of-code,特別有意思,代碼也很優(yōu)雅。 能學(xué)es6 自己翻譯,能學(xué)英語 代碼很美,很優(yōu)雅,美即正義 函數(shù)式表達(dá),享受 ...
閱讀 2137·2021-09-06 15:02
閱讀 1753·2021-08-13 15:02
閱讀 2318·2019-08-29 14:14
閱讀 1478·2019-08-26 13:55
閱讀 560·2019-08-26 13:46
閱讀 3415·2019-08-26 11:41
閱讀 532·2019-08-26 10:27
閱讀 3279·2019-08-23 15:28