數組去重問題
src: http://yiminghe.javaeye.com/blog/524716
很經典的問題,去除數組中的重複元素,上網搜了一下,發現大多數無論轉載還是原創都是這個解法:
錯誤解法:
Js代碼
- function uniq(array) {
- var map={};
- var re=[];
- for(var i=0,l=array.length;i<l;i++) {
- if(typeof map[array[i]] == "undefined"){
- map[array[i]]=1;
- re.push(array[i]);
- }
- }
- return re;
- }
function uniq(array) {var map={};var re=[];for(var i=0,l=array.length;i<l;i++) {if(typeof map[array[i]] == "undefined"){map[array[i]]=1;re.push(array[i]);}}return re;}
如果用過java等進階語言的話,初看這段代碼確實沒有什麼問題:下面的例子:
Js代碼
- uniq([1,2,1,2,4]);
uniq([1,2,1,2,4]);
也能正常運行。
可再試試下面的例子:
Js代碼
- uniq([{x:1},"[object Object]"]);
- uniq([{x:1},{z:2}]);
uniq([{x:1},"[object Object]"]);uniq([{x:1},{z:2}]);
運行一下就會知道錯在哪裡了!
HashMap In Java :
在 java 中如 HashMap 類可以使用對象做為 key (內部實現使用 hashcode散列到桶 以及桶內equals[預設記憶體位址]比較),如:
Java代碼
- class Holder {
- int i;
- }
- public class Test3 {
-
- /**
- * @param args
- */
- public static void main(String[] args) {
- HashMap<Holder, Holder> map=new HashMap<Holder, Holder>();
- Holder key= new Holder();
- Holder value= new Holder();
- value.i=1;
- map.put(key, value);
- Holder key2=new Holder();
- System.out.println(map.get(key).i);
- System.out.println(map.get(key2));
- }
-
- }
class Holder {int i;}public class Test3 {/** * @param args */public static void main(String[] args) {HashMap<Holder, Holder> map=new HashMap<Holder, Holder>();Holder key= new Holder();Holder value= new Holder();value.i=1;map.put(key, value);Holder key2=new Holder(); System.out.println(map.get(key).i);System.out.println(map.get(key2));}}
Object In Javascript:
而在 javascript 中畢竟沒有map,只有對象這個概念,而對象則要求其屬性值必須為字串,如果提供給對象的屬性不是字串,那麼則會自動調用 toString 方法轉化為字串形式,例如:
Js代碼
- var x={};
- var y={
- toString:function(){
- return "z";
- }
- };
-
- x[y]=1;
- alert(x["z"]);
var x={};var y={ toString:function(){ return "z"; }};x[y]=1;alert(x["z"]);
那麼由上述例子就可以知道第一個程式為什麼是錯誤的了 。
正確答案:
我們無法利用進階語言提供的map類庫,那就只好兩遍遍曆數組了,也是 taobao ued提供的標準答案:
注意 === 使用。
Js代碼
- /**
- *unique the array
- *@param {Array} array array to unique
- *@return {Array} uniqued array ,note change parameter
- */
- function undulpicate(array){
- for(var i=0;i<array.length;i++) {
- for(var j=i+1;j<array.length;j++) {
- //注意 ===
- if(array[i]===array[j]) {
- array.splice(j,1);
- j--;
- }
- }
- }
- return array;
- }
/***unique the array*@param {Array} array array to unique*@return {Array} uniqued array ,note change parameter*/function undulpicate(array){for(var i=0;i<array.length;i++) {for(var j=i+1;j<array.length;j++) {//注意 ===if(array[i]===array[j]) {array.splice(j,1);j--;}}}return array;}
ps: Jquery Uniq Node
如果我們確認數組裡每個元素都是對象,那麼可以用加標籤的方式,給對象元素添加標籤,從而把時間複雜度提升到 O(n) :
Js代碼
- var x={z:1};
- var y={q:2};
- function uniqObjects(array){
- var re=[];
- for(var i=0,l=array.length;i<l;i++) {
- if(typeof array[i]["_uniqObjects"] == "undefined"){
- //添加標籤
- array[i]["_uniqObjects"]=1;
- re.push(array[i]);
- }
- }
- //取出標籤
- for(var i=0,l=re.length;i<l;i++) {
- delete re[i]["_uniqObjects"];
- }
- return re;
- }
- uniqObjects([x,y,x]);
var x={z:1};var y={q:2};function uniqObjects(array){var re=[];for(var i=0,l=array.length;i<l;i++) {if(typeof array[i]["_uniqObjects"] == "undefined"){//添加標籤 array[i]["_uniqObjects"]=1;re.push(array[i]);}} //取出標籤for(var i=0,l=re.length;i<l;i++) {delete re[i]["_uniqObjects"];}return re;}uniqObjects([x,y,x]);
這也正是 jquery 的思路,由於每個元素都是節點數組,當然可以這樣做了:
Js代碼
- unique: function( array ) {
- var ret = [], done = {};
-
- try {
-
- for ( var i = 0, length = array.length; i < length; i++ ) {
- var id = jQuery.data( array[ i ] );
-
- if ( !done[ id ] ) {
- done[ id ] = true;
- ret.push( array[ i ] );
- }
- }
-
- } catch( e ) {
- ret = array;
- }
-
- return ret;
- },
unique: function( array ) {var ret = [], done = {};try {for ( var i = 0, length = array.length; i < length; i++ ) {var id = jQuery.data( array[ i ] );if ( !done[ id ] ) {done[ id ] = true;ret.push( array[ i ] );}}} catch( e ) {ret = array;}return ret;},
注意:對基本類型,如 number,string,不要使用這種方式,它們會產生臨時對象,並不能達到預期效果!