国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

JavaScript數(shù)組去重的6個(gè)方法

2019-11-19 17:50:03
字體:
供稿:網(wǎng)友

方法一

無需思考,我們可以得到 O(n^2) 復(fù)雜度的解法。定義一個(gè)變量數(shù)組 res 保存結(jié)果,遍歷需要去重的數(shù)組,如果該元素已經(jīng)存在在 res 中了,則說明是重復(fù)的元素,如果沒有,則放入 res 中。

 function unique(a) { var res = []; for (var i = 0, len = a.length; i < len; i++) { var item = a[i]; for (var j = 0, jLen = res.length; j < jLen; j++) { if (res[j] === item) break; } if (j === jLen) res.push(item); } return res;}var a = [1, 1, '1', '2', 1];var ans = unique(a);console.log(ans); // => [1, "1", "2"]

代碼非常簡單,那么是否能更簡潔些?如果不考慮瀏覽器兼容,我們可以用 ES5 提供的 Array.prototype.indexOf 方法來簡化代碼。

function unique(a) { var res = []; for (var i = 0, len = a.length; i < len; i++) { var item = a[i]; (res.indexOf(item) === -1) && res.push(item); } return res;}var a = [1, 1, '1', '2', 1];var ans = unique(a);console.log(ans); // => [1, "1", "2"]

既然用了 indexOf,那么不妨再加上 filter。

function unique(a) { var res = a.filter(function(item, index, array) { return array.indexOf(item) === index; }); return res;}var a = [1, 1, '1', '2', 1];var ans = unique(a);console.log(ans); // => [1, "1", "2"]

方法二

法一是將原數(shù)組中的元素和結(jié)果數(shù)組中的元素一一比較,我們可以換個(gè)思路,將原數(shù)組中重復(fù)元素的最后一個(gè)元素放入結(jié)果數(shù)組中。

function unique(a) { var res = a.filter(function(item, index, array) { return array.indexOf(item) === index; }); return res;}var a = [1, 1, '1', '2', 1];var ans = unique(a);console.log(ans); // => [1, "1", "2"]

雖然復(fù)雜度還是 O(n^2),但是可以看到結(jié)果不同,1 出現(xiàn)在了數(shù)組最后面,因?yàn)榻Y(jié)果數(shù)組取的是元素最后一次出現(xiàn)的位置。

方法三(sort)

如果筆試面試時(shí)只答出了上面這樣 O(n^2) 的方案,可能還不能使面試官滿意,下面就來說幾種進(jìn)階方案。

將數(shù)組用 sort 排序后,理論上相同的元素會(huì)被放在相鄰的位置,那么比較前后位置的元素就可以了。

function unique(a) { return a.concat().sort().filter(function(item, pos, ary) { return !pos || item != ary[pos - 1]; });}var a = [1, 1, 3, 2, 1, 2, 4];var ans = unique(a);console.log(ans); // => [1, 2, 3, 4]

但是問題又來了,1 和 "1" 會(huì)被排在一起,不同的 Object 會(huì)被排在一起,因?yàn)樗鼈?toString() 的結(jié)果相同,所以會(huì)出現(xiàn)這樣的錯(cuò)誤:

function unique(a) { return a.concat().sort().filter(function(item, pos, ary) { return !pos || item != ary[pos - 1]; });}var a = [1, 1, 3, 2, 1, 2, 4, '1'];var ans = unique(a);console.log(ans); // => [1, 2, 3, 4]

當(dāng)然你完全可以針對數(shù)組中可能出現(xiàn)的不同類型,來寫這個(gè)比較函數(shù)。不過這似乎有點(diǎn)麻煩。

方法四 (object)

用 JavaScript 中的 Object 對象來當(dāng)做哈希表,這也是幾年前筆試時(shí)的解法,跟 sort 一樣,可以去重完全由 Number 基本類型組成的數(shù)組。

function unique(a) { var seen = {}; return a.filter(function(item) { return seen.hasOwnProperty(item) ? false : (seen[item] = true); });}var a = [1, 1, 3, 2, 1, 2, 4];var ans = unique(a);console.log(ans); // => [1, 3, 2, 4]

還是和方法三一樣的問題,因?yàn)?Object 的 key 值都是 String 類型,所以對于 1 和 "1" 無法分別,我們可以稍微改進(jìn)下,將類型也存入 key 中。

function unique(a) { var ret = []; var hash = {}; for (var i = 0, len = a.length; i < len; i++) { var item = a[i]; var key = typeof(item) + item; if (hash[key] !== 1) { ret.push(item); hash[key] = 1; } } return ret;}var a = [1, 1, 3, 2, '4', 1, 2, 4, '1'];var ans = unique(a);console.log(ans); // => [1, 3, 2, "4", 4, "1"]

雖然解決了討厭的 1 和 "1" 的問題,但是還有別的問題!

function unique(a) { var ret = []; var hash = {}; for (var i = 0, len = a.length; i < len; i++) { var item = a[i]; var key = typeof(item) + item; if (hash[key] !== 1) { ret.push(item); hash[key] = 1; } } return ret;}var a = [{name: "hanzichi"}, {age: 30}, new String(1), new Number(1)];var ans = unique(a);console.log(ans); // => [Object, String]

但是如果數(shù)組元素全部是基礎(chǔ)類型的 Number 值,鍵值對法應(yīng)該是最高效的!

方法五 (ES6)

ES6 部署了 Set 以及 Array.from 方法,太強(qiáng)大了!如果瀏覽器支持,完全可以這樣:

function unique(a) { return Array.from(new Set(a));}var a = [{name: "hanzichi"}, {age: 30}, new String(1), new Number(1)];var ans = unique(a);console.log(ans); // => [Object, Object, String, Number]

_.unique

最后來看看 underscore 對此的實(shí)現(xiàn)方式,underscore 將此封裝到了 _.unique 方法中,調(diào)用方式為 _.unique(array, [isSorted], [iteratee])。其中第一個(gè)參數(shù)是必須的,是需要去重的數(shù)組,第二個(gè)參數(shù)可選,如果數(shù)組有序,則可以傳入布爾值 true,第三個(gè)參數(shù)可選,如果需要對數(shù)組迭代的結(jié)果去重,則可以傳入一個(gè)迭代函數(shù)。而數(shù)組元素去重是基于 === 運(yùn)算符的。

其實(shí)很簡單,underscore 中的實(shí)現(xiàn)方式和上面的方法一相似。

我們來看它的核心代碼:

for (var i = 0, length = getLength(array); i < length; i++) { var value = array[i], // 如果指定了迭代函數(shù) // 則對數(shù)組每一個(gè)元素進(jìn)行迭代 computed = iteratee ? iteratee(value, i, array) : value; // 如果是有序數(shù)組,則當(dāng)前元素只需跟上一個(gè)元素對比即可 // 用 seen 變量保存上一個(gè)元素 if (isSorted) { // 如果 i === 0,則直接 push // 否則比較當(dāng)前元素是否和前一個(gè)元素相等 if (!i || seen !== computed) result.push(value); // seen 保存當(dāng)前元素,供下一次對比 seen = computed; } else if (iteratee) { // 如果 seen[] 中沒有 computed 這個(gè)元素值 if (!_.contains(seen, computed)) { seen.push(computed); result.push(value); } } else if (!_.contains(result, value)) {  // 如果不用經(jīng)過迭代函數(shù)計(jì)算,也就不用 seen[] 變量了 result.push(value); }}

外面的循環(huán)遍歷數(shù)組元素,對于每個(gè)元素,如果數(shù)組有序,則和前一個(gè)元素比較,如果相同,則已經(jīng)出現(xiàn)過,不加入到結(jié)果數(shù)組中,否則則加入。而如果有迭代函數(shù),則計(jì)算傳入迭代函數(shù)后的值,對值去重,調(diào)用 .contains 方法,而該方法的核心就是調(diào)用.indexOf 方法,和我們上面說的方法一異曲同工。

 以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持武林網(wǎng)!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 抚松县| 阿尔山市| 平凉市| 都江堰市| 青岛市| 三河市| 易门县| 太湖县| 新和县| 金华市| 镇康县| 富蕴县| 尖扎县| 萨迦县| 秭归县| 安新县| 林甸县| 东台市| 砚山县| 孝义市| 武隆县| 霸州市| 哈尔滨市| 峨边| 宁武县| 万州区| 藁城市| 玛沁县| 定南县| 永新县| 河北区| 丹凤县| 华坪县| 余姚市| 宁夏| 缙云县| 陵川县| 昌邑市| 班玛县| 大理市| 天柱县|