這應該是JavaScript 中數(shù)組操作方法(含ES5及ES5+)較全的總結了吧

一、ES5 中數(shù)組操作方法

ES5 中數(shù)組操作方法總結

詳盡使用參看 MDN_Array

二衙伶、ES5+ 中數(shù)組操作方法

ES5+ 數(shù)組操作方法

除了 flat 和 flatMap 方法詳解,其它詳解參看 ES6 數(shù)組給我們帶來哪些操作便利害碾?

flat()和flatMap()本質上就是是歸納(reduce) 與 合并(concat)的操作矢劲。

Array.prototype.flat()

flat() 方法會按照一個可指定的深度遞歸遍歷數(shù)組,并將所有元素與遍歷到的子數(shù)組中的元素合并為一個新數(shù)組返回慌随。

  • flat()方法最基本的作用就是數(shù)組降維
var arr1 = [1, 2, [3, 4]];
arr1.flat(); 
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

//使用 Infinity 作為深度芬沉,展開任意深度的嵌套數(shù)組
arr3.flat(Infinity); 
// [1, 2, 3, 4, 5, 6]
  • 其次躺同,還可以利用 flat() 方法的特性來去除數(shù)組的空項
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]

具體可參看 MDN_Array.prototype.flat()

Array.prototype.flatMap()

flatMap() 方法首先使用映射函數(shù)映射每個元素,然后將結果壓縮成一個新數(shù)組丸逸。它與 map 和 深度值1的 flat 幾乎相同蹋艺,但 flatMap 通常在合并成一種方法的效率稍微高一些。 這里我們拿map方法與flatMap方法做一個比較椭员。

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

arr1.map(x => [x * 2]); 
// [[2], [4], [6], [8]]

arr1.flatMap(x => [x * 2]);
// [2, 4, 6, 8]

// 只會將 flatMap 中的函數(shù)返回的數(shù)組 “壓平” 一層
arr1.flatMap(x => [[x * 2]]);
// [[2], [4], [6], [8]]

具體參看 MDN_Array.prototype.flatMap()

三车海、數(shù)組操作方法對數(shù)組自身的影響

是否改變數(shù)組自身

四、九種數(shù)組去重方法

9重數(shù)組去重方法

測試數(shù)組去重時間代碼示例

const arr = [];
// 生成[0, 100000]之間的隨機數(shù)
for (let i = 0; i < 100000; i++) {
  arr.push(0 + Math.floor((100000 - 0 + 1) * Math.random()))
}

// ...實現(xiàn)算法

console.time('test');
arr.unique();
console.timeEnd('test');
1隘击、雙重去重

基本思路:通過拿出一個元素和剩下的元素依次比較,如果全部不相等則證明此元素為唯一研铆。

Array.prototype.unique = function () {
  const newArray = [];
  let isRepeat;
  for (let i = 0; i < this.length; i++) {
    isRepeat = false;
    for (let j = 0; j < newArray.length; j++) {
      if (this[i] === newArray[j]) {
        isRepeat = true;
        break;
      }
    }
    if (!isRepeat) {
      newArray.push(this[i]);
    }
  }
  return newArray;
}

測試時間:

test: 3032.134033203125ms

缺點:復雜度太高

2埋同、indexOf

基本思路:如果索引不是第一個索引,說明是重復值棵红。

Array.prototype.unique = function () {
  const newArray = [];
  this.forEach(item => {
    if (newArray.indexOf(item) === -1) {
      newArray.push(item);
    }
  });
  return newArray;
}

測試時間:

test: 6951.115966796875ms
3凶赁、sort

基本思路:先對原數(shù)組進行排序,然后再進行元素比較逆甜。

Array.prototype.unique = function () {
  const newArray = [];
  this.sort();
  for (let i = 0; i < this.length; i++) {
    if (this[i] !== this[i + 1]) {
      newArray.push(this[i]);
    }
  }
  return newArray;
}

測試時間:

test: 72.129150390625ms
4虱肄、includes

基本思路:判斷新數(shù)組中是否含有已存在的項

Array.prototype.unique = function () {
  const newArray = [];
  this.forEach(item => {
    if (!newArray.includes(item)) {
      newArray.push(item);
    }
  });
  return newArray;
}

測試時間:

test: 5378.988037109375ms
5、reduce

reduce() 方法接收一個函數(shù)作為累加器交煞,數(shù)組中的每個值(從左到右)開始縮減咏窿,最終計算為一個值

Array.prototype.unique = function () {
  return this.sort().reduce((init, current) => {
    if(init.length === 0 || init[init.length - 1] !== current){
      init.push(current);
    }
    return init;
  }, []);
}

測試時間:

test: 69.05908203125ms

更好的使用場景:對象數(shù)組中去掉重復的對象

6、對象鍵值對keys()

基本思路:利用了對象的key不可以重復的特性來進行去重素征。

Array.prototype.unique = function () {
  const newArray = [];
  const tmp = {};
  for (let i = 0; i < this.length; i++) {
    if (!tmp[typeof this[i] + this[i]]) {
      tmp[typeof this[i] + this[i]] = 1;
      newArray.push(this[i]);
    }
  }
  return newArray;
}

測試時間:

test: 333.0009765625ms

更適合處理如對象這樣的復雜的數(shù)據(jù)類型

7集嵌、Map 數(shù)據(jù)結構

兩種針對簡單數(shù)據(jù)類型的去重:
方法一:

Array.prototype.unique = function () {
  const newArray = [];
  const tmp = new Map();
  for(let i = 0; i < this.length; i++){
        if(!tmp.get(this[i])){
            tmp.set(this[i], 1);
            newArray.push(this[i]);
        }
    }
    return newArray;
}

方法二:

Array.prototype.unique = function () {
  const tmp = new Map();
  return this.filter(item => {
    return !tmp.has(item) && tmp.set(item, 1);
  })
}

分別的測試時間:

test: 53.268798828125ms
test: 41.73193359375ms
8、Set 數(shù)據(jù)結構

也有兩種簡單的數(shù)據(jù)類型去重的:
方法一:

Array.prototype.unique = function () {
  const set = new Set(this);
  return Array.from(set);
}

方法二:

Array.prototype.unique = function () {
  return [...new Set(this)];
}

測試時間:

test: 17.760009765625ms
test: 19.72509765625ms

上面兩種方法只適用簡單的數(shù)據(jù)類型去重御毅,如果遇到一個比較復雜的對象數(shù)組根欧,就去重失敗,如下代碼示例:

let arr = [
    { name: 'a', num: 1},
    { name: 'b', num: 1},
    { name: 'c', num: 1},
    { name: 'd', num: 1},
    { name: 'a', num: 1},
    { name: 'a', num: 1},
    { name: 'a', num: 1}
]
function unique (arr) {
    return [...new Set(arr)]
}
console.log(unique(arr)) // 結果為原數(shù)組端蛆,有興趣可以復制代碼試一下

因為 set 數(shù)據(jù)結構認為對象永不相等凤粗,即使是兩個空對象,在 set 結構內部也是不等的
如何解決呢今豆?
這里需要借助 JSON.stringfy() 和 JSON.parse() 序列化對象:

// ES6對象數(shù)組所有屬性去重,篩選每個數(shù)組項的字符
function unique(arr) {
    const map = new Map()
    return arr.filter( item => !map.has(JSON.stringify(item)) && map.set(JSON.stringify(item), 1))
}

function unique(arr) {
      return [...new Set(arr.map(e => JSON.stringify(e)))].map(e => JSON.parse(e))
  }

// 兩者出來的結果
[
    { name: 'a', num: 1},
    { name: 'b', num: 1},
    { name: 'c', num: 1},
    { name: 'd', num: 1}
]
9嫌拣、underscore.js 方法庫

測試代碼

_.uniq(arr);

測試時間

test: 3640.329833984375ms

總結
除了考慮時間復雜度外、性能之外晚凿,還要考慮數(shù)組元素的數(shù)據(jù)類型等問題權衡選擇出采用哪種算法亭罪,通過上面的幾個測試用例,可以看出利用 Set 和 Map 數(shù)據(jù)結構去重的效率會高一些歼秽。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末应役,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌箩祥,老刑警劉巖院崇,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異袍祖,居然都是意外死亡底瓣,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門蕉陋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捐凭,“玉大人,你說我怎么就攤上這事凳鬓∽鲁Γ” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵缩举,是天一觀的道長垦梆。 經(jīng)常有香客問我,道長仅孩,這世上最難降的妖魔是什么托猩? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮辽慕,結果婚禮上京腥,老公的妹妹穿的比我還像新娘。我一直安慰自己鼻百,他們只是感情好绞旅,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著温艇,像睡著了一般因悲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勺爱,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天晃琳,我揣著相機與錄音,去河邊找鬼琐鲁。 笑死卫旱,一個胖子當著我的面吹牛,可吹牛的內容都是我干的围段。 我是一名探鬼主播顾翼,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼奈泪!你這毒婦竟也來了适贸?” 一聲冷哼從身側響起灸芳,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拜姿,沒想到半個月后烙样,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡蕊肥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年谒获,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壁却。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡批狱,死狀恐怖,靈堂內的尸體忽然破棺而出展东,到底是詐尸還是另有隱情精耐,我是刑警寧澤,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布琅锻,位于F島的核電站,受9級特大地震影響向胡,放射性物質發(fā)生泄漏恼蓬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一僵芹、第九天 我趴在偏房一處隱蔽的房頂上張望处硬。 院中可真熱鬧,春花似錦拇派、人聲如沸荷辕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疮方。三九已至,卻和暖如春茧彤,著一層夾襖步出監(jiān)牢的瞬間骡显,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工曾掂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惫谤,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓珠洗,卻偏偏與公主長得像溜歪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子许蓖,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內容