陣列處理方法

本頁介紹到的方法有:

Array.prototype.filter()

filter() 會回傳一個陣列,其條件是 return 後方為 true 的物件,很適合用在搜尋符合條件的資料。
功能: 將經指定的函式運算後,由原陣列中通過該函式檢驗的元素回傳一個新陣列。
改變: 不會改變元陣列。
語法
    var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])

回傳值: 回傳新陣列,原陣列不改變
參數: callback 函式、thisArg,第二參數可忽略。

範例:過濾所有的小數字

以下範例會用 filter() 建立一個把所有小於 10 的元素都移掉的陣列。
function isBigEnough(value) {
  return value >= 10;
}

var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);

document.write("Input: [12, 5, 8, 130, 44]");
document.write("<p>Output: number >=10 : " + filtered);

// filtered is [12, 130, 44]//-->

看效果

我們也可以用它搭配可去掉空字串的字串方法trim(),再將陣列沒用或空的元素刪除,就可得到一個新的、乾淨的陣列。

let arr = ['Hello', '', 'Hi', null, undefined, 'Ciao', ' '];

let newArr = arr.filter(function (inutile) {
 return inutile && inutile.trim();
});
newArr; // ['Hello', 'Hi', 'Ciao']
需注意,在IE9(不包含IE9)以下的版本並不支援trim()方法。

看效果

透過filter()函式的第一參數:callback 函式所指定的過濾條件,返回一個新陣列 (非常好用)。 例如我們只想保留陣列裡,字串長度大於三的字串元素,可以輕易地取得。

let arr = ['Jack',  'Joe', 'John', 'May', 'Su', 'Ada'];
let arr2 = arr.filter(function(value) {
  return value.length > 3;
});
arr2.join('、'); //  Jack、John

看效果

更簡潔的方式使用箭頭函式(Arrow function ):

let arr = ['Jack', 'Joe', 'John', 'May', 'Su', 'Ada'];
let arr2 = arr.filter(value => value.length > 3);

看效果

利用filter(),我們也可以輕鬆地去除陣列裡重複的元素,可以達到這樣的效果是因為使用indexOf()會回傳第一個元素位置的(index), 如果之後有重複元素的位置與indexOf()回傳的位置不相等,就會被filter()過濾掉。而這時的過濾結果,只會先保留第一個找到的元素, 第二個重複的元素就不會被放進回傳的陣列裡了。

let arr = ['B', 'A', 'E', 'C', 'A', 'F', 'G', 'E'];

let newArr = arr.filter(function (element, index, self) {
   return self.indexOf(element) === index;
});

看效果

我們更可以把這些去掉重複的元素,且讓陣列的排序整齊一點的功能,包成一個函式,使用起來就方便多了。

let arr = ['B', 'A', 'E', 'C', 'A', 'F', 'G', 'E'];

function removeDuplicates(originArray) {
  let result = originArray.filter(function(value, index, arrSelf){
    return arrSelf.indexOf(value) === index
    });
  return result.sort();
};

removeDuplicates(array);

看效果

Array.prototype.find()

find() 與 filter() 很像,但 find() 只會回傳一次值,且是第一次為 true 的值。
var  people=[
  { name: 'Casper',  like: '鍋燒意麵',  age: 18 },
  { name: 'Wang',    like: '炒麵',     age: 24 } ,
  { name: 'Bobo',    like: '蘿蔔泥',   age: 1 },
  { name: '滷蛋',     like: '蘿蔔泥',   age: 3  }
]

var findEmpty = people.find(function(item, index, array){
});
document.write(findEmpty);          // 沒有條件,會是 undefined

var findAgeThan5 = people.find(function(item, index, array){
  return item.age > 5;           // 取得大於五歲的
});
document.write("<p>Age>5: " + findAgeThan5.name);       // 雖然答案有兩個,但只會回傳 Casper 這一個物件

var findLike = people.find(function(item, index, array){
  return item.like === '蘿蔔泥';  // 取得陣列 like === '蘿蔔泥'
});
document.write("<p>Like 蘿蔔泥: " + findLike.name);
//-->

看效果

Array.prototype.forEach()

forEach 是這幾個陣列函式最單純的一個,不會額外回傳值,只單純執行每個陣列內的物件或值。
    var even_nums = [2,4,6,8];
    document.write("Input: " + even_nums);
    even_nums.forEach(function (value, index, array) {
        array[index] += 2;
    });

看效果

列印內含物件的陣列,用 forEach() 也很方便,如下例:

var  people=[
  { name: 'Casper',  like: '鍋燒意麵',  age: 18 },
  { name: 'Wang',    like: '炒麵',     age: 24 } ,
  { name: 'Bobo',    like: '蘿蔔泥',   age: 1 },
  { name: '滷蛋',     like: '蘿蔔泥',   age: 3  }
]
document.write("<p>people: ");
people.forEach(function (value, index, array) {
   document.write("<br>{" + "name:" + array[index].name + ", like: " + array[index].like
                          + ", age: " + array[index].age +"}")
});

看效果

上例的列印,只適用於該陣列。列印一般陣列,請參照下例:

function prtobj(obj){
    document.write("<br>{");
    Object.keys(obj).forEach(e=>document.write(e+":"+obj[e]+", "))
    document.write("}");
};

document.write("<p>people:");
people.forEach(value =>prtobj(value));

看效果

Array.prototype.map()

用陣列使用 map() 方法呼叫函式的話,就可以讓陣列中每個元素執行完該函式後,將每個元素的執行結果回傳到一個新的陣列。
var newArr = arr.map(function (value, index, array){  //...  });

例:陣列中每項都加2:

    var even_nums = [2,4,6,8];
    var even_nums2=even_nums.map(function (value, index, array) {
        return value+2;
    });

看效果

或用箭頭函式:

    var even_nums = [2,4,6,8];
    var even_nums2=even_nums.map(value=>value+2);

看效果

求平方根

	var numbers = [1, 4, 9];
	var roots = numbers.map(Math.sqrt);     //map會return一個新的array

看效果

使用 map 將陣列中的物件變更格式

以下程式碼取出一陣列,將其中物件變更格式後建立為一個新的陣列並傳回。
var kvArray = [{key: 1, value: 10},
               {key: 2, value: 20},
               {key: 3, value: 30}];

var reformattedArray = kvArray.map(function(obj) {
   var rObj = {};
   rObj[obj.key] = obj.value;
   return rObj;
});

看效果

Array.prototype.every()

every() 可以檢查所有的陣列是否符合條件,這僅會回傳一個值 true or false,可以用來檢查陣列中的內容是否符合特定條件。
    var nums = [1,3,5,7,9];
    var ans1=nums.every(function (value, index, array) {
        return value>=3;
    });
    var ans2=nums.every(function (value, index, array) {
        return value%2 == 1;
    });

看效果

Array.prototype.some()

some() 與 every() 非常接近,都是回傳 true or false,差異僅在 every() 需完全符合,some() 僅需要部分符合。
    var nums = [1,3,5,7,9];
    var ans1=nums.some(function (value, index, array) {
        return value>=3;
    });
    var ans2=nums.some(function (value, index, array) {
        return value%2 == 0;
    });

看效果

Array.prototype.reduce()

reduce() 和其他幾個差異就很大了,reduce 方法跟其他陣列方法(例如:map、filter)的差別是它會 return 一個值,而不是一個新陣列。 他可以與前一個回傳的值再次作運算,參數包含以下:
    Array.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)

例題

<script language="JavaScript">
var  nums=[1,2,3,4,5];

var reducePlus = nums.reduce(function(accumulator, value, index, array){
    return accumulator + value;
}, 0);                                    // 傳入初始化值為 0
document.write("<p>總和為: " + reducePlus);                  // 總和為 15

var reducePlus = nums.reduce(function(accumulator, value, index, array){
  return Math.max( accumulator, value ); // 與前一個值比較哪個大
}, 0);
document.write("<p>最大值為: " + reducePlus);                  // 最大值為 5
</script>
上述範例若未提供預設值,accumulator(累計值)就會取陣列的第一個元素也就是 1,而 value 就會從陣列的第二個值開始 loop。

看效果

例題

var  people=[
  { name: 'Casper',  like: '鍋燒意麵',  age: 18 },
  { name: 'Wang',    like: '炒麵',     age: 24 } ,
  { name: 'Bobo',    like: '蘿蔔泥',   age: 1 },
  { name: '滷蛋',     like: '蘿蔔泥',   age: 3  }
]

var reduceEmpty = people.reduce(function(accumulator, value, index, array){
});
document.write(reduceEmpty);                 // 沒有條件,會是 undefined

var reducePlus = people.reduce(function(accumulator, value, index, array){
  return accumulator + value.age;
}, 0);                                    // 傳入初始化值為 0
document.write("<p>總和為: " + reducePlus);                  // 總和為 46

var reducePlus = people.reduce(function(accumulator, value, index, array){
  return Math.max( accumulator, value.age ); // 與前一個值比較哪個大
}, 0);
document.write("<p>最大值為: " + reducePlus);                  // 最大值為 24

看效果

合併陣列

var arr = [['a', 'b'], ['c', 'd'], ['e', 'f']];
var arr.reduce(function(accumulator, value, index, array){
  return accumulator.concat(value);
}, []);
document.write("<p>合併後的陣列為: " + reduceArr);      // ['a', 'b', 'c', 'd', 'e', 'f'];

看效果

參考資料

  1. 卡斯伯
  2. iT 邦幫忙