一邊學習前端,一邊經過博客的形式本身總結一些東西,固然也但願幫助一些和我同樣開始學前端的小夥伴。前端
若是出現錯誤,請在評論中指出,我也好本身糾正本身的錯誤es6
此文是鏈接我以前的一篇總結文章,能夠去我主頁搜索 數組
author: thomaszhoubash
一到多維數組的最值求解
for循環或者foreach(比for快點)app
forEach方法dom
<script>
//forEach比普通循環效率高點
var arr = [1,23,45,66,75,111,4];
Array.prototype.max = function () {
var max = this[0];
this.forEach (function (eval) {
if (eval > max) {
max = eval;
}
});
return max;
}
console.log(arr.max());//111
</script>
複製代碼
<script>
//reduce()方法
Array.prototype.max = function () {
var max = this[0];
return this.reduce(function (preValue, curValue) {
// prevalue是每次迭代的結果
return preValue > curValue ? preValue : curValue;
})
}
console.log(arr.max());
複製代碼
var arr = [1,23,45,66,75,111,4];
// 內置函數Math.max()和Math.min()的括號裏面不能放數組對象,而是必須放具體的值,以下:
console.log(Math.max(arr));//NaN
console.log(Math.max(1,2,43,5,6,777));//77
console.log(Math.min(1,2,43,5,6,777));//1
console.log(Math.max());//沒有參數的時候,-Infinity
複製代碼
如下方法使用來解決不能傳遞對象參數的問題!函數
如何解決???
// 須要利用別的方法來引用數組對象
//法一:Function.prototype.apply()
console.log(Math.max.apply(Math, arr));//111
法二:
Array.prototype.max = function () {
return Math.max.apply(Math, arr)
//return Math.max.apply({}, arr)這個同上條語句
//不明白爲何是{}??
}
console.log(arr.max());//111
複製代碼
法三:ES6方法學習
// es6的方法-----...展開運算符
//使數組中的值在函數調用的位置展開
const arrayMax = arr => Math.max(...arr);//最大值
const arrayMin = arr => Math.min(...arr);//最小值
console.log(arrMax(arr));//111
</script>
複製代碼
雙層for循環是最簡單的方法,ui
var arr2 = [[1,20,5],[3,45,564],[34,12]];
var newMap1 = arr2.map(function (item) {
//map是遍歷最外層,item就是每一個子數組
return item.reduce(function (preVal, curVal) {
//對每一個子數組item進行求出最值的操做,並返回
return preVal > curVal ? preVal: curVal;
})
});
console.log(newMap1);//[20,564,34]
//Math.max求出最值
console.log(Math.max(...newMap1));//564
複製代碼
step1: 在外層數組中使用Array.prototype.map()方法遍歷數組。this
step2: 使用map()方法遍歷數組,會調用一個回調函數,在這個回調函數中, 使用reduce()方法對每一個子數組group進行合併,將值返回到一個新數組中。
step3: 而在使用reduce()方法時,一樣會調用一個回調函數,這個回調函數只作了一件事情, 就是子數組中的元素作爲比較,若是curVal大於preVal,將會返回current, 不然返回prev,最終獲得每一個子數組中最大值
方法二(最佳)---目前沒看懂
var arr2 = [[1,20,5],[3,45,564],[34,12]];
function largestOfFour (arr) {
return arr.map(Function.apply.bind(Math.max, null));
}
console.log(largestOfFour(arr2)); //[20, 564, 34]
複製代碼
這個方案,使用Function.bind方法建立一個特殊的回調函數,就相似於Math.max方法同樣,但其有一個Function.prototype.apply功能,將數組做爲它的參數。
先對主數組中的每一個元素作遍歷,也就是數組內部的每一個子數組
使用map()方法須要一個回調函數,用來找出內部每一個數組中的最大值。須要建立一個函數,讓Math.max能接受輸入的數組工做。換句話說,這是很是簡單並且這樣工做也很是的好,如Math.max([9,43,20,6]);將會返回最大值43
Function.prototype.apply方法工做能夠接受數組作爲參數,但函數經過調用上下文,這事情就有點複雜。例如Math.max.apply(null,[9,43,20,6])將調用一個Max.max方法,但這樣的方法找起來不容易。
這裏給Function.prototype.apply方法傳遞了一個null參數,告訴Math.max不須要任何上下文。
由於arr.map()須要一個回調函數,而不僅是一個表達式,咱們在Function.bind方法中提供了一個函數
由於Function.prototype.apply是一個靜態方法,相似一個函數對象,咱們能夠稱之爲Function.prototype.apply上綁定了一個Function.prototype.bind。例如: Function.apply.bind
如今能夠經過Function.prototype.apply.bind回調函數指定其上下文,好比在這個示例中的Math.max方法
因爲是嵌入到Function.prototype.apply方法,須要一個上下文做爲第一個參數,並且這個上下文仍是一個虛假的。
因此咱們將null做爲第二個參數傳遞給Function.prototype.apply.bind,而且綁定一個上下文,這個上下文就是Math.max方法
因爲Math.max是獨立於任何上下文的,因此它會忽略Function.prototype.apply方法調用的虛假上下文
咱們使用Function.prototype.apply.bind(Math.max,null)讓一個新函數接受arr.map值,好比數組中的子數組
很巧妙的方法!!!!!!!!也是多位數組的方法
var arr2 = [[1,20,5],[3,45,564],[34,12]];
var new1 = function (arr) {
// 經過join先把數組裏面的值用,拼接成字符串
// 用split將字符串拼接爲數組
return arr.join(',').split(',');
}(arr2)
// console.log(largestOfFour(arr2));
console.log(Math.max(...new1));//564
複製代碼
上文使用不一樣的方法實現了從二維數組中取出子數組中最大值,而且將這些最大值從新組成一個新數組,若是延伸一下,取出裏面的最大值時,還須要使用Array.prototype.max函數,函數中經過Math.max.apply({},this)取得最大值。不過若是不是二維數組,那上述方法將沒法取出數組中最大的值。
var arr2 = [333,[3,45,564],[34,12,[1,4000]]];
var new1 = function (arr) {
// 經過join先把數組裏面的值用,拼接成字符串
// 用split將字符串拼接爲數組
return arr.join(',').split(',');
}(arr2)
// console.log(largestOfFour(arr2));
console.log(Math.max(...new1));//4000
複製代碼
數組內部元素隨機排列
var arr = [1,2,3,4,5,7,8,9]
arr.sort(function () {
return Math.random() - 0.5
})
複製代碼
計數數組中值的出現次數
使用reduce()將每一個值添加到累加器,初始值爲0,總和除以數組長度。
const average = arr => arr.reduce((pre, cur) => pre + cur, 0) / arr.length;
// 箭頭函數,若是函數只有一條語句,不要加"{}"和 ";"
// average([1,2,3]) -> 2
複製代碼
每次遇到數組中的特定值時,使用reduce()來遞增計數器。
const arrayCount = (arr, value) => {
let count = 0;
arr.forEach(val => {
val === value? count += 1: count += 0;
});
return count;
}
console.log(arrayCount([1,1,2,3,4], 1)); // 2
複製代碼
或者reduce方法
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
// countOccurrences([1,1,2,1,2,3], 1) -> 3
複製代碼
找出數組間不一樣項-相同項
從b建立一個Set,而後在a上使用Array.filter(),只保留b中不包含的值。
es6: Set結構的has方法,是用來查找值的
const difference = (a, b) => {
let s = new Set(b);
return a.filter(x => !s.has(x));
}
console.log(difference([1,2,3], [1,2]));//[3]
複製代碼
上面是 !s.has(x)),若是改爲s.has(x)),那就是求數組a中和數組b的交集
const difference = (a, b) => {
let s = new Set(b);
return a.filter(x => s.has(x));//將!去掉了
}
console.log(difference([1,2,3,2], [1,2,4,2]));//[1, 2, 2]
複製代碼
過濾數組中的非惟一值
const arrayIntersection = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
// console.log(arrayIntersection([1,2,2,3,4,4,5])); // [1,3,5]
複製代碼
數組合並
const arrayConcat = (arr, ...args) => {
let array = arr.concat(...args);
return array;
};
console.log(arrayConcat([1], [2,6], 5, [[2],10])); // [1, 2, 6, 5, [2], 10]
複製代碼
缺點:只能將二維數組降成一維,如上面[2]就是二維數組
這就聯繫到深度展開數組的操做,看下面的flatten深度展開數組
flatten深度展開數組
其實就是數組降維:將嵌套多層的數組(嵌套能夠是任何層數)轉換爲只有一層的數組
let arr = [1,[2],[[[3,[10]],4],5]];
let newArr = [];
function changeArr(arr){
for(var i=0;i<arr.length;i++){
//遍歷arr數組得每個元素,這裏也能夠用forEach
if(arr[i] instanceof Array){
//判斷元素是否爲數組
changeArr(arr[i])
//元素爲數組則繼續調用changeArr方法遍歷
}else{
newArr.push(arr[i])
//元素不是數組則能夠直接push進新數組
}
}
//此上的判斷也能夠直接用三元表達式
}
changeArr(arr);
console.log(newArr); // [1, 2, 3, 10, 4, 5]
複製代碼
使用遞歸去遞減深度。使用 Array.reduce() 和 Array.concat() 來合併元素或數組。基本狀況下,當深度爲 1 時中止遞歸。省略第二個參數,展開深度爲 1。
const flattenDepth = (arr, depth = 1) =>
depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
: arr.reduce((a, v) => a.concat(v), []);
// 降2維
console.log(flattenDepth([1,[2],[[[3],4],5]], 2)); // [1,2,[3],4,5]
// 降3維
console.log(flattenDepth([1,[2],[[[3],4],5]], 3)); // [1, 2, 3, 4, 5]
複製代碼
數組中元素僅基本類型的元素或數組,能夠轉換爲字符串,不存在循環引用的狀況。
function flatten(arr) { return arr.toString().split(',')}
// arr.toString() 結果是字符串形式的1,2,3,4
<!--// 變成字符形式的數組-->
console.log(flatten([1,[2],[[3]], [[[4]]]])) //["1", "2", "3", "4"]
複製代碼
解決辦法:最後再遍歷一遍數組,用Number轉化爲數字!
斐波那契數列是0、一、一、二、三、五、八、1三、2一、34...
這個是迭代方式,遞歸方法太耗時
function fibonacci(n) {
let fibo = [0, 1];
if (n < 2) {
return n;
}
for (let i = 2; i <= n; i++) {
fibo.push(fibo[i-1] + fibo[i-2]);
}
return fibo[n];
}
console.log(fibonacci(0)); // 0
console.log(fibonacci(1)); // 1
console.log(fibonacci(6)); // 8
複製代碼
一些簡單的應用
其實就是去掉最後n個值,利用arr.slice(0,-1)。以0爲起點,去一個是-1,去兩個是-2,以此類推,
const initial = arr => arr.slice(0, -1);
// initial([1,2,3]) -> [1,2]
複製代碼
使用Array(n)建立所需長度的數組,fill(v)以填充所需的值,能夠忽略value使用默認值0。
const initializeArray = (n, value = 0) => Array(n).fill(value);
// initializeArray(5, 2) -> [2,2,2,2,2]
複製代碼
使用 Array(end-start) 建立一個所需長度的數組,使用 Array.map() 來填充範圍中的所需值。 你能夠省略start,默認值爲 0。
const initializeArrayRange = (end, start = 0) =>
Array.apply(null, Array(end - start)).map((v, i) => i + start);
// initializeArrayRange(5) -> [0,1,2,3,4]
複製代碼
返回arr.slice(-1)[0]
const last = arr => arr.slice(-1)[0];
//arr.slice(-1)獲得的是數組[3]
console.log(last([1,2,3])); // 3
複製代碼
使用 Array.slice() 獲得一個包含第一個元素的數組。 若是索引超出範圍,則返回 []。(譯者注:超過索引返回 undefind) 省略第二個參數 n 來獲取數組的第一個元素。
const nth = (arr, n=0) => (n>0? arr.slice(n,n+1) : arr.slice(n))[0];
// nth(['a','b','c'],1) -> 'b'
// nth(['a','b','b']-2) -> 'a'
複製代碼