1. 程式人生 > >陣列最大值與第二大值交換-javascript實現

陣列最大值與第二大值交換-javascript實現

看著這個題目,我們可能覺得很low,這麼個破題,還用的著寫篇部落格麼!我一開始也覺得不值當。直到今天我知道了這種實現方式。

如題:

var arr1 = [1,2,4,6,9,3];

交換以後就是這樣:

var arr2 = [1,2,4,9,6,3];

不要告訴我你的思路是用for迴圈挨個遍歷,找到最大的和次大的交換位置。我們不討論這種方式。如果是這樣就沒有必要寫一篇部落格了。

切入正題,你知道Math.max()這個Math物件的原生方法嗎?不知道的自行百度。這個方法可以取得一組數字的最大值。

Math.max(1,2,4,9,6,3)// =>結果是9,你造嗎!!!

但是:

var arr2 = [1,2,4,9,6,3];
Math.max(arr2)// =>結果是NaN,你造嗎!!!

Math.max()函式的引數是n個引數列表,而不接收一個數組的形式([param1[,param2[,…[,paramN]]]]),可以通過apply的方式巧妙地解決這個問題!

var arr2 = [1,2,4,9,6,3];
Math.max.apply(null,arr2)// =>結果是9,達到預期效果

我們從一些資料上得知apply的第一個引數為傳入的作用域,null表示當前作用域,第二個引數為arguments型別。但不是陣列型別。可以理解為類陣列。關於arguments的型別一會兒再做討論。

我們先解決陣列最大值和次大值交換。說到這裡了。直接上程式碼吧。

var change = '',// 儲存最大值
    arr = [1,3,5,7,9],
    max1 = Math.max.apply(null,arr),// 查詢最大
    max1_index = arr.indexOf(max1);// 查詢最大元素索引
change = arr[max1_index];// 儲存最大值
arr[max1_index] = 0;// 把最大值置零,再次篩選最大值
console.log(arr);// 此時的陣列是[1,3,5,7,0]

var max2 = Math.max.apply(null
,arr), max2_index = arr.indexOf(max2); arr[max1_index] = arr[max2_index];// 次大賦值給最大 arr[max2_index] = change;// 把剛才得到的最大賦值給次大 console.log(arr);// 此時的陣列是[1,3,5,9,7]

這個問題搞定了。我們看看剛才遺留的那個關於arguments和陣列的問題。

Javascript函式中的引數arguments是個物件,而不是陣列。但它可以類似陣列那樣通過數字下表訪問其中的元素,而且它也有length屬性標識它的元素的個數。
我們可以用

Array.prototype.slice.call();

來進行arguments=》陣列的轉化

(function() {
      var args = arguments;//獲取arguments
      console.log(args, Object.prototype.toString.call(args)); // [1, 2, 3] "[object Arguments]" 
      var argsArr = Array.prototype.slice.call(args);
      console.log(argsArr, Object.prototype.toString.call(argsArr)); // [1, 2, 3] "[object Array]" 
    }(1,2,3))

這裡需要說明一下,我們使用

Object.prototype.toString.call();

來判斷一個位置結構的型別

說到這裡,我們知道使用Array.prototype.slice.call()可以將函式的arguments物件轉化為陣列。

那麼我們接著擴充套件 Array.prototype.slice 的用法

  • 字串轉化為陣列
console.log(Array.prototype.slice.call('string')); // => ["s", "t", "r", "i", "n", "g"]
  • 如果引數型別為number、boolean、object的話,則會得到空陣列。
console.log(Array.prototype.slice.call({1:'44',3:'66'})); // => []

console.log(Array.prototype.slice.call(true)); // => []

console.log(Array.prototype.slice.call(22)); // => []
  • 結構體要想轉化為陣列,要加上一個length屬性
console.log(Array.prototype.slice.call({0: 'zero', 1: 'one', 2: 'obj', length: 3}));  // =>["zero", "one", 'obj'] 
  • clone 陣列
var oriArr = [1,2,3],
    newArr = srcArr.slice(0);
console.log(oriArr, newArr);// =>[1,2,3] [1,2,3]
console.log(oriArr == newArr);// =>false

寫了這麼多,主要因apply這個方法而起。
本文涉及到的知識點:

  • Math.max(1,2,4,9,6,3)
  • Math.max.apply(null,arr)
  • Object.prototype.toString.call()
  • Array.prototype.slice.call()
  • arr.slice()