>

会用ES5里面数组的indexOf()方法sbf282.com:,复制代

- 编辑:澳门博发娱乐官网 -

会用ES5里面数组的indexOf()方法sbf282.com:,复制代

Array.prototype.includes()

Array.prototype.includes()是ES二〇一六中新添的办法,用于决断数组中是不是包含有个别成分,所以地点使用indexOf()办法的第四个本子能够改写成如下版本:

JavaScript

function unique(arr) { var ret = []; arr.forEach(function(item){ if(!ret.includes(item)){ ret.push(item); } }); return ret; }

1
2
3
4
5
6
7
8
9
function unique(arr) {
    var ret = [];
    arr.forEach(function(item){
        if(!ret.includes(item)){
            ret.push(item);
        }
    });
    return ret;
}

那么,你猜猜,includes()又是用什么样格局来相比较的啊?假使想当然的话,会认为必定跟indexOf()相像喽。可是,技师的世界里最怕想当然。翻生机勃勃翻标准,发掘它事实上是利用的另大器晚成种比较艺术,叫作“SameValueZero”相比较()。

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number, then
    a. If x is NaN and y is NaN, return true.
    b. If x is +0 and y is -0, return true.
    c. If x is -0 and y is +0, return true.
    d. If x is the same Number value as y, return true.
    e. Return false.
  3. Return SameValueNonNumber(x, y).

注意2.a,如果xy都是NaN,则返回true!也就是includes()是能够精确判别是不是含有了NaN的。我们写大器晚成段代码验证一下:

JavaScript

var arr = [1, 2, NaN]; arr.indexOf(NaN); // -1 arr.includes(NaN); // true

1
2
3
var arr = [1, 2, NaN];
arr.indexOf(NaN); // -1
arr.includes(NaN); // true

能够看看indexOf()includes()对待NaN的一坐一起是一心不平等的。

鉴于Map使用单独的接口来存取数据,所以并非操心key会和停放属性重名(如上文提到的__proto__卡塔 尔(英语:State of Qatar)。使用Map改写一下大家的去重方法:

 1 function removeDuplicates(arr) {
 2 
 3     var temp = {}, r = [];
 4 
 5     for (var i in arr)
 6 
 7         temp[arr[i]] = true;
 8 
 9     for (var k in temp)
10 
11         r.push(k);
12 
13     return r;
14 
15 }
16 
17 //用法
18 
19 var fruits = ['apple', 'orange', 'peach', 'apple', 'strawberry', 'orange', 'strawberry', 'orange'];
20 
21 var uniquefruits = removeDuplicates(fruits);
22 alert(uniquefruits);

Array.prototype.swap = function($a, $b)
{
 if($a == $b)
  return;

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"]

对象和指标

在关系相比较的时候,还大概会遇上对象。具体来说,大概能够分为两种情景:纯对象、实例对象、别的体系的目标。

纯对象

纯对象(plain object卡塔 尔(英语:State of Qatar)具体指什么并非丰裕显眼,为减弱不必要的争辩,下文中央银行使纯对象指代由字面量生成的、成员中不含函数和日期、正则表达式等品种的目的。

假诺一向拿五个对象举行相比较,不管是==还是===,不容置疑都是不等于的。不过在实质上选择时,这样的平整是还是不是必然满意大家的需求?举个例证,大家的应用中有五个布局项:

JavaScript

// 原本有二日性子 // var prop1 = 1; // var prop2 = 2; // 重构代码时八个属性被平放同叁个对象中 var config = { prop1: 1, prop2: 2 };

1
2
3
4
5
6
7
8
// 原来有两个属性
// var prop1 = 1;
// var prop2 = 2;
// 重构代码时两个属性被放到同一个对象中
var config = {
    prop1: 1,
    prop2: 2
};

倘使在少数场景下,大家供给相比较五遍运行的布置项是还是不是后生可畏律。在重构前,大家分别相比一次运维的prop1prop2就能够。而在重构后,咱们可能供给比较config指标所表示的安顿项是否风姿浪漫致。在此么的场所下,直接用==或者===来相比对象,获得的而不是大家期望的结果。

在如此的面貌下,大家只怕需求自定义一些办法来管理指标的可比。平淡无奇的或许是透过JSON.stringify()对目的开展体系化之后再相比字符串,当然这些进程不要全盘有限支撑,只是二个思路。

借使您感到这一个景况是胡编的话,能够再回想一下断言库,雷同是依附对象成员,判别结果是还是不是和预期切合。

实例对象

实例对象首要指通过构造函数(类卡塔 尔(阿拉伯语:قطر‎生成的指标。那样的靶子和纯对象同样,间接相比较都是差异的,但也会胜过须要看清是不是是同风度翩翩对象的情况。平日来讲,因为这种对象有相比较复杂的内部结构(以致有风流洒脱部分数额在原型上卡塔尔,无法直接从表面临比是不是等于。相比可靠的论断格局是由构造函数(类卡塔 尔(阿拉伯语:قطر‎来提供静态方法或然实例方法来判定是不是等于。

JavaScript

var a = Klass(); var b = Klass(); Klass.isEqual(a, b);

1
2
3
var a = Klass();
var b = Klass();
Klass.isEqual(a, b);

任何对象

此外对象首要指数组、日期、正则表达式等那类在Object底工上派生出来的靶子。那类对象各自有各自的特殊性,平时供给根据气象来组织剖断形式,决定五个指标是还是不是等于。

举个例子说,日期对象,可能要求经过Date.prototype.getTime()办法得届期间戳来判断是还是不是意味着未有差距时刻。正则说明式恐怕须求经过toString()格局获得到原始字面量来剖断是还是不是是相近的正则表明式。

console.log && isNaN;

    for (var i in arr)

    var res = new Array(len);
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        res[i] = fun.call(thisp, this[i], i, this);
    }

方法四 (object)

Array.prototype.indexOf()

在有的本子的去重中,用到了Array.prototype.indexOf()方法:

JavaScript

function unique(arr) { return arr.filter(function(item, index){ // indexOf重临第三个索引值, // 假诺当前索引不是第一个目录,表明是重复值 return arr.indexOf(item) === index; }); }

1
2
3
4
5
6
7
function unique(arr) {
    return arr.filter(function(item, index){
        // indexOf返回第一个索引值,
        // 如果当前索引不是第一个索引,说明是重复值
        return arr.indexOf(item) === index;
    });
}

JavaScript

function unique(arr) { var ret = []; arr.forEach(function(item){ if(ret.indexOf(item) === -1){ ret.push(item); } }); return ret; }

1
2
3
4
5
6
7
8
9
function unique(arr) {
    var ret = [];
    arr.forEach(function(item){
        if(ret.indexOf(item) === -1){
            ret.push(item);
        }
    });
    return ret;
}

既然=====在要素相等的可比中是有伟大反差的,那么indexOf的气象又何以呢?超越四分之二的稿子都不曾提起那点,于是只可以求助标准。通过标准(卡塔尔国,我们理解了indexOf()动用的是严刻相比较,也正是===

重新重申:依据前文所述,===不能够管理NaN的相等性剖断。

这种方案没什么大主题素材,用于去重的可比部分也是和煦编写实现(arr[i] === arr[j]卡塔 尔(阿拉伯语:قطر‎,所以相等性能够和谐针对上文说起的各类状态再说特殊处理。独一比较受非议的是选择了双重循环,时间复杂度比较高,品质平日。使用对象key来去重

/*选取了聚众的思维,有序不重复*/
function removeDuplicates(arr) {

 return false;
}

 

==和===

在部分篇章中,看见某有些数组去重的法子,在认清成分是不是等于时,使用的是==相比运算符。有目共睹,那个运算符在可比前会先查看成分类型,当类型不均等时会做隐式类型转变。那实际是生机勃勃种非常不小心翼翼的做法。因为不大概区分在做规避类型转变后值同样的要素,譬喻0''falsenullundefined等。

再者,还应该有十分的大可能率现身一些必须要白人问号的结果,比方:

JavaScript

[] == ![]; //true

1
[] == ![]; //true

倘让你商量过'a'.trim()那样的代码的话,不明白是还是不是产生过如此的疑点:'a'明明是多个原始值,它干吗能够一直调用.trim()方法呢?当然,很恐怕你早已知晓答案:因为JS在实行那样的代码的时候会对原始值做二次包装,让'a'产生多少个字符串对象,然后实行那几个目的的不二秘诀,施行完事后再把那个包裹对象脱掉。能够用上面包车型大巴代码来掌握:// 'a'.trim();

首先种:也是最笨的呢。

    var res = new Array();
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

关于 _.unique 方法的亲力亲为代码,能够仿照效法

NaN

初看NaN时,超轻巧把它当成和nullundefined相似的单身数据类型。但实质上,它是数字类型。

JavaScript

// number console.log(typeof NaN);

1
2
// number
console.log(typeof NaN);

遵照规范,比较运算中生龙活虎旦有贰个值为NaN,则相比较结实为false,所以会有下面这个看起来略蛋疼的定论:

JavaScript

// 全都是false 0 < NaN; 0 > NaN; 0 == NaN; 0 === NaN;

1
2
3
4
5
// 全都是false
0 < NaN;
0 > NaN;
0 == NaN;
0 === NaN;

以最后二个表明式0 === NaN为例,在典型中有明显规定():

  1. If Type(x) is Number, then
    a. If x is NaN, return false.
    b. If y is NaN, return false.
    c. If x is the same Number value as y, return true.
    d. If x is +0 and y is −0, return true.
    e. If x is −0 and y is +0, return true.
    f. Return false.

那意味着任何关系到NaN的场地都不能大约地采纳比较运算来剖断是不是等于。比较不错的方法只可以是运用isNaN()

JavaScript

var a = NaN; var b = NaN;   // true console.log(isNaN(a) && isNaN(b));

1
2
3
4
5
var a = NaN;
var b = NaN;
 
// true
console.log(isNaN(a) && isNaN(b));

f. Return false.

选拔正则

    return res;
  };
}
if (!Array.prototype.some)
{
  Array.prototype.some = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

就算复杂度依然 O(n^2),但是足以看见结果差别,1 出以后了数组最前面,因为结果数组取的是因素最终贰遍现身的岗位。

小结

最终,用四个测量试验用例总计一下文中现身的各种去重方法:

JavaScript

var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},[],[],/a/,/a/] console.log(unique(arr));

1
2
var arr = [1,1,'1','1',0,0,'0','0',undefined,undefined,null,null,NaN,NaN,{},{},[],[],/a/,/a/]
console.log(unique(arr));

测量试验中绝非概念对象的相比艺术,由此暗中同意景况下,对象不去重是精确的结果,去重是不科学的结果。

方法 结果 说明
indexOf#1 NaN被去掉
indexOf#2 NaN重复
includes 正确
双重循环#1 NaN重复
双重循环#2 NaN重复
对象#1 字符串和数字无法区分,对象、数组、正则表达式被去重
对象#2 对象、数组、正则表达式被去重
对象#3 对象、数组被去重,正则表达式被消失 JSON.stringify(/a/)结果为{},和空对象一样
Map 正确
Set 正确

末段的末尾:任何脱离场景谈技能都以妄谈,本文也同样。去重这道题,未有准确答案,请依据气象接收特出的去重方法。

1 赞 3 收藏 评论

sbf282.com 1

prop1: 1,

透过和谐申明过了,代码如下:

    return true;
  };
}
if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

function unique(arr){
    var res=[];
    for(var i=0,len=arr.length;i<len;i++){
        var obj = arr[i];
        for(var j=0,jlen = res.length;j<jlen;j++){
            if(res[j]===obj) break;            
        }
        if(jlen===j)res.push(obj);
    }
    return res;
}
var arr=[1,1,'2','1',3,4]
arr = unique(arr);
console.log(arr);

概念再一次(相等卡塔 尔(阿拉伯语:قطر‎

要去重,首先得定义,什么叫作“重复”,即现实到代码来讲,两个数据在什么样情形下得以算是非常的。这并非三个超轻巧的标题。

对于原始值来说,大家相当轻易想到11是优秀的,'1''1'也是杰出的。那么,1'1'是非常的么?

比如那一个标题万幸说,只要回答“是”恐怕“不是”就可以。那么上面那么些景况就没那么轻便了。

sbf282.com 2

Array.prototype.unique5 = function() {
var res = [], hash = {};
for(var i=0, elem; (elem = this[i]) != null; i++) {
if (!hash[elem])
{
res.push(elem);
hash[elem] = true;
}
}
return res;
}

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this &&
          fun.call(thisp, this[i], i, this))
        return true;
    }

var a = [{name: "hanzichi"}, {age: 30}, new String(1), new Number(1)];

var ans = unique(a);

console.log(ans); // => [Object, String]

原始值和包裹对象

看完NaN是还是不是头都大了。好了,大家来轻巧一下,看生龙活虎看原始值和包装对象那风姿浪漫对情侣。

固然您钻探过'a'.trim()这么的代码的话,不知底是否产生过如此的问号:'a'刚毅是三个原始值(字符串卡塔尔国,它怎么可以够直接调用.trim()措施吗?当然,很大概你已经驾驭答案:因为JS在奉行那样的代码的时候会对原始值做一次包装,让'a'产生多个字符串对象,然后实行那么些指标的主意,试行完事后再把那一个包裹对象脱掉。能够用上面包车型大巴代码来通晓:

JavaScript

// 'a'.trim(); var tmp = new String('a'); tmp.trim();

1
2
3
// 'a'.trim();
var tmp = new String('a');
tmp.trim();

这段代码只是帮忙大家通晓的。但包装对象这么些定义在JS中却是真实存在的。

JavaScript

var a = new String('a'); var b = 'b';

1
2
var a = new String('a');
var b = 'b';

a正是贰个打包对象,它和b平等,代表叁个字符串。它们都得以应用字符串的各样法子(比方trim()卡塔 尔(阿拉伯语:قطر‎,也得以参预字符串运算(+号连接等卡塔 尔(英语:State of Qatar)。

但他们有三个首要的分歧:类型分化!

JavaScript

typeof a; // object typeof b; // string

1
2
typeof a; // object
typeof b; // string

在做字符串相比较的时候,类型的两样会招致结果有意气风发部分意外:

JavaScript

var a1 = 'a'; var a2 = new String('a'); var a3 = new String('a'); a1 == a2; // true a1 == a3; // true a2 == a3; // true a1 === a2; // false a1 === a3; // false a2 === a3; // false

1
2
3
4
5
6
7
8
9
var a1 = 'a';
var a2 = new String('a');
var a3 = new String('a');
a1 == a2; // true
a1 == a3; // true
a2 == a3; // true
a1 === a2; // false
a1 === a3; // false
a2 === a3; // false

相近是意味字符串a的变量,在接受严谨相比较时竟然不是相等的,在直觉上那是风流浪漫件比较难选择的作业,在各样草销情况下,也非常轻巧忽视这个细节。

a1 == a3; // true

 

    return res;
  };
}
if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

 

遍历

再一次遍历是最轻易想到的去重方案:

JavaScript

function unique(arr) { var ret = []; var len = arr.length; var isRepeat; for(var i=0; i<len; i++) { isRepeat = false; for(var j=i+1; j<len; j++) { if(arr[i] === arr[j]){ isRepeat = true; break; } } if(!isRepeat){ ret.push(arr[i]); } } return ret; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function unique(arr) {
    var ret = [];
    var len = arr.length;
    var isRepeat;
    for(var i=0; i<len; i++) {
        isRepeat = false;
        for(var j=i+1; j<len; j++) {
            if(arr[i] === arr[j]){
                isRepeat = true;
                break;
            }
        }
        if(!isRepeat){
            ret.push(arr[i]);
        }
    }
    return ret;
}

双重遍历还恐怕有三个优化版本,但是原理和复杂度大约完全平等:

JavaScript

function unique(arr) { var ret = []; var len = arr.length; for(var i=0; i<len; i++){ for(var j=i+1; j<len; j++){ if(arr[i] === arr[j]){ j = ++i; } } ret.push(arr[i]); } return ret; }

1
2
3
4
5
6
7
8
9
10
11
12
13
function unique(arr) {
    var ret = [];
    var len = arr.length;
    for(var i=0; i<len; i++){
        for(var j=i+1; j<len; j++){
            if(arr[i] === arr[j]){
                j = ++i;
            }
        }
        ret.push(arr[i]);
    }
    return ret;
}

这种方案没什么大主题素材,用于去重的可比部分也是和谐编写完毕(arr[i] === arr[j]卡塔尔,所以相等性可以团结针对上文提及的各样状态再说特殊管理。唯意气风发相比受非议的是采用了双重循环,时间复杂度比较高,品质平日。

若果那几个主题材料幸而说,只要回答“是”可能“不是”就可以。那么下边那一个情状就没那么轻易了。NaN

Array.prototype.unique1 = function () {
var r = new Array();
label:for(var i = 0, n = this.length; i < n; i++) {
for(var x = 0, y = r.length; x < y; x++) {
if(r[x] == this[i]) {
continue label;
}
}
r[r.length] = this[i];
}
return r;
}
第二种:那么些正则天书相符。

使用

虽说缓慢解决了嫌恶的 1 和 "1" 的题目,不过还会有其余难题!

Map Key

能够看看,使用对象key来拍卖数组去重的标题,其实是风华正茂件相比费力的职业,管理不好超级轻巧产生结果不许确。而这个主题素材的根本原因正是因为key在使用时有限定。

那么,能或不可能有风流倜傥种key使用未有节制的对象呢?答案是——真的有!那就是ES二〇一五中的Map

Map是后生可畏种新的数据类型,能够把它想象成key类型未有界定的对象。其余,它的存取使用单独的get()set()接口。

JavaScript

var tmp = new Map(); tmp.set(1, 1); tmp.get(1); // 1 tmp.set('2', 2); tmp.get('2'); // 2 tmp.set(true, 3); tmp.get(true); // 3 tmp.set(undefined, 4); tmp.get(undefined); // 4 tmp.set(NaN, 5); tmp.get(NaN); // 5 var arr = [], obj = {}; tmp.set(arr, 6); tmp.get(arr); // 6 tmp.set(obj, 7); tmp.get(obj); // 7

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var tmp = new Map();
tmp.set(1, 1);
tmp.get(1); // 1
tmp.set('2', 2);
tmp.get('2'); // 2
tmp.set(true, 3);
tmp.get(true); // 3
tmp.set(undefined, 4);
tmp.get(undefined); // 4
tmp.set(NaN, 5);
tmp.get(NaN); // 5
var arr = [], obj = {};
tmp.set(arr, 6);
tmp.get(arr); // 6
tmp.set(obj, 7);
tmp.get(obj); // 7

是因为Map使用单独的接口来存取数据,所以不要忧虑key会和停放属性重名(如上文提到的__proto__)。使用Map改写一下大家的去重方法:

JavaScript

function unique(arr) { var ret = []; var len = arr.length; var tmp = new Map(); for(var i=0; i<len; i++){ if(!tmp.get(arr[i])){ tmp.set(arr[i], 1); ret.push(arr[i]); } } return ret; }

1
2
3
4
5
6
7
8
9
10
11
12
function unique(arr) {
    var ret = [];
    var len = arr.length;
    var tmp = new Map();
    for(var i=0; i<len; i++){
        if(!tmp.get(arr[i])){
            tmp.set(arr[i], 1);
            ret.push(arr[i]);
        }
    }
    return ret;
}

细想一下,那样一个好像简单的须求,借使要产生康健,涉及的学问和内需在乎的地点确实不菲。定义再一次

len = 0;
var tempArr=[];
for(var i in temp) {
tempArr[len++] = i;
}
return tempArr;
}
第八种:先排序,前项比后项。这么些艺术挺轻巧的,但也实用

 if($index != -1)
  this.splice($index, 1);
}

for (var i = 0, length = getLength(array); i  length; i++) {

  var value = array[i],

      // 假若钦点了迭代函数

      // 则对数组每一个要素实行迭代

      computed = iteratee ? iteratee(value, i, array) : value;

 

  // 假设是有序数组,则当前成分只需跟上二个成分相比就能够

  // 用 seen 变量保存上二个要素

  if (isSorted) {

    // 如果 i === 0,则直接 push

    // 不然相比较当前成分是不是和前叁个成分相等

    if (!i || seen !== computed) result.push(value);

    // seen 保存当前因素,供下二遍相比

    seen = computed;

  } else if (iteratee) {

    // 如果 seen[] 中尚无 computed 这几个元素值

    if (!_.contains(seen, computed)) {

      seen.push(computed);

      result.push(value);

    }

  } else if (!_.contains(result, value)) {  

    // 要是不用经过迭代函数总结,也就绝不 seen[] 变量了

    result.push(value);

  }

}

局地方案

从上边的一大段文字中,咱们得以观望,要看清三个因素是或不是等于(重复卡塔 尔(英语:State of Qatar)实际不是大器晚成件轻易的业务。在通晓了那个背景后,大家来看一些前面未有涉嫌到的去重方案。

而第三个难点,假若像上文所说,在同意对指标开展自定义的可比准绳,也得以将对象种类化之后作为key来利用。这里为简便起见,使用JSON.stringify()实行连串化。

    var temp = {}, r = [];

 var i=start;
 var res = [];
 while(i<end){
  res.push(this[i++]);
 }
 return res; 
}
//arr.unshift(ele1,ele2,ele3....)
Array.prototype.unshift =function(){
 Array.prototype.splice.apply(this,[0,0].concat(Array.prototype.slice.apply(this,arguments)));
}

 

Set

既然都用到了ES二零一四,数组这件业务不能够再轻便一点么?当然能够。

除了Map以外,ES二零一五还引进了风流浪漫种叫作Set的数据类型。看名就会猜到其意义,Set就算聚焦的情趣,它不容许再一次成分现身,那点和数学中对集中的概念依然比较像的。

JavaScript

var s = new Set(); s.add(1); s.add('1'); s.add(null); s.add(undefined); s.add(NaN); s.add(true); s.add([]); s.add({});

1
2
3
4
5
6
7
8
9
var s = new Set();
s.add(1);
s.add('1');
s.add(null);
s.add(undefined);
s.add(NaN);
s.add(true);
s.add([]);
s.add({});

假定你再一次添加同叁个因素的话,Set中只会设有三个。富含NaN也是如此。于是我们想到,这么好的特色,如若能和数组相互调换,不就能够去重了吗?

JavaScript

function unique(arr){ var set = new Set(arr); return Array.from(set); }

1
2
3
4
function unique(arr){
    var set = new Set(arr);
    return Array.from(set);
}

咱俩谈谈了这么久的作业,居然两行代码化解了,大概出乎意料。

而是,不要理会着兴奋了。有一句话是如此说的“不要因为走得太远而忘了怎么出发”。大家怎么要为数组去重呢?因为大家想得到不另行的因素列表。而既然已经有Set了,我们为啥还要心高气傲,使用数组呢?是否在须要去重之处下,直接运用Set就解决难点了?那个主题素材值得思索。

tmp.get; // 1

        r.push(k);

 for(var i=0;i<arr.length;i++){
  this[i]=arr[i];
 }
 this.length=arr.length;
 return res;
}
Array.prototype.shift = function(){ if(!this) return[];return this.splice(0,1)[0];}

方法二

运用对象key来去重

JavaScript

function unique(arr) { var ret = []; var len = arr.length; var tmp = {}; for(var i=0; i<len; i++){ if(!tmp[arr[i]]){ tmp[arr[i]] = 1; ret.push(arr[i]); } } return ret; }

1
2
3
4
5
6
7
8
9
10
11
12
function unique(arr) {
    var ret = [];
    var len = arr.length;
    var tmp = {};
    for(var i=0; i<len; i++){
        if(!tmp[arr[i]]){
            tmp[arr[i]] = 1;
            ret.push(arr[i]);
        }
    }
    return ret;
}

这种方法是选取了指标(tmp卡塔尔的key不可能另行的特征来拓宽去重。但由于指标key只可以为字符串,因而这种去重方法有大多局限性:

  1. 没辙区分隐式类型转换来字符串后豆蔻梢头致的值,例如1'1'
  2. 心有余而力不足管理百端待举数据类型,比如对象(因为对象作为key会产生[object Object]
  3. 破例数据,比方'__proto__'会挂掉,因为tmp对象的__proto__属性不能够被重写

对此第一点,有人提议可认为对象的key扩张三个项目,恐怕将品种放到对象的value中来解决:

JavaScript

function unique(arr) { var ret = []; var len = arr.length; var tmp = {}; var tmpKey; for(var i=0; i<len; i++){ tmpKey = typeof arr[i] + arr[i]; if(!tmp[tmpKey]){ tmp[tmpKey] = 1; ret.push(arr[i]); } } return ret; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function unique(arr) {
    var ret = [];
    var len = arr.length;
    var tmp = {};
    var tmpKey;
    for(var i=0; i<len; i++){
        tmpKey = typeof arr[i] + arr[i];
        if(!tmp[tmpKey]){
            tmp[tmpKey] = 1;
            ret.push(arr[i]);
        }
    }
    return ret;
}

该方案也还要缓慢解决第多个难点。

而第二个难题,要是像上文所说,在同意对目的举行自定义的相比法则,也得以将目的类别化之后作为key来使用。这里为简便起见,使用JSON.stringify()进展类别化。

JavaScript

function unique(arr) { var ret = []; var len = arr.length; var tmp = {}; var tmpKey; for(var i=0; i<len; i++){ tmpKey = typeof arr[i] + JSON.stringify(arr[i]); if(!tmp[tmpKey]){ tmp[tmpKey] = 1; ret.push(arr[i]); } } return ret; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function unique(arr) {
    var ret = [];
    var len = arr.length;
    var tmp = {};
    var tmpKey;
    for(var i=0; i<len; i++){
        tmpKey = typeof arr[i] + JSON.stringify(arr[i]);
        if(!tmp[tmpKey]){
            tmp[tmpKey] = 1;
            ret.push(arr[i]);
        }
    }
    return ret;
}

sbf282.com 3

还可以有种更老妪能解的写法:

 var arr =[],res=[];
 var iarr=0,ires=0,i=0;

 

也谈JavaScript数组去重

2017/01/07 · JavaScript · 数组

最早的作品出处: TooBug(@TooBug)   

JavaScript的数组去重是三个不符合时机的话题了。随便搜大器晚成搜就能够找到超级多不一致版本的解法。

今天在果壳网络见到大器晚成篇文章,也写数组去重,首要正视的不二诀窍是将应用数组成分当作对象key来去重。作者在果壳网转载了“用对象key去重不是个好法子…”然后小编问哪些才是引入的办法。

细想一下,那样三个近乎轻巧的须要,要是要成功完善,涉及的学识和内需当心之处确实不少,于是诞生此文。

那么,能还是不可能有大器晚成种key使用没有节制的对象啊?答案是——真的有!那正是ES2016中的Map。Map是大器晚成种新的数据类型,能够把它想象成key类型未有约束的对象。别的,它的存取使用单独的get接口。var tmp = new Map();

Array.prototype.unique2 = function () {
return this.sort().join(",,").replace(/(,|^)([^,]+)(,,2)+(,|$)/g,"$1$2$4").replace(/,,+/g,",").replace(/,$/,"").split(",");
}
其二种:使用对象的【hasOwnProperty】方法

 return -1;
}
if (!Array.prototype.lastIndexOf)
{
  Array.prototype.lastIndexOf = function(elt /*, from*/)
  {
    var len = this.length;

 

tmp.get; // 5

/**
* 字符串去重
* rn字符串分隔符
* $1分割后的字符串,$2字符串的目录
* 以分隔符将字符串分割,依据分割后的数组成分的个数举办巡回相比较
*/
    function strUnique(){
        var str = "abc, abcd, abc, abcde, abcd, abcde";
        var ret = [];
        str.replace(/[^,]+/g, function($1, $2){
            (str.indexOf($1) == $2) && ret.push($1);
        });
        alert(ret);
        return ret;
    }

你可能感兴趣的篇章:

  • 以JSON方式将JS中Array对象数组传至后台的章程
  • JavaScript 推断剖断有个别对象是Object还是多少个Array
  • js中推断Object、Array、Function等援用类型对象是或不是等于
  • JavaScript数组Array对象增删成分方法总括
  • Javascript中判别变量是数组依然对象(array依然object)
  • javascript Array对象使用小结
  • JScript内置对象Array五月素的删除方法
  • JavaScript中Array 对象相关的几个方法
  • JavaScript中的Array对象使用验证
  • javascript中绘身绘色的Array对象精解

方法五 (ES6)

b. If y is NaN, return false.

 1     function strUnique(){
 2         var str = "abc, abcd, abc, abcde, abcd, abcde";
 3         var ret = [];
 4         str.replace(/[^,]+/g, function($1, $2){
 5             (str.indexOf($1) == $2) && ret.push($1);
 6         });
 7         alert(ret);
 8         return ret;
 9     }
10     
11 strUnique();

Array.prototype.pop = function() { return this.splice(this.length-1,1)[0];}

 

在局地篇章中,见到某部分数组去重的主意,在认清成分是不是等于时,使用的是==相比较运算符。家弦户诵,这几个运算符在可比前会先查看成分类型,当类型不相相同的时间会做隐式类型转变。这件事实上是大器晚成种分外超级大心的做法。因为不恐怕区分在做逃匿类型调换后值同样的要素,举个例子0、''、false、null、undefined等。

}

if (!Array.prototype.every)
{
  Array.prototype.every = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

 

arr.indexOf; // -1

}

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this &&
          !fun.call(thisp, this[i], i, this))
        return false;
    }

1.只要不依据于任何措施,初级写法应该是:

这段代码只是帮忙我们知晓的。但包装对象这些定义在JS中却是真实存在的。var a = new String;

Array.prototype.unique4 = function () {
var temp = new Array();
this.sort();
for(i = 0; i < this.length; i++) {
if( this[i] == this[i+1]) {
continue;
}
temp[temp.length]=this[i];
}
return temp;

    for (; from > -1; from--)
    {
      if (from in this &&
          this[from] === elt)
        return from;
    }
    return -1;
  };
}
Array.prototype.insertAt = function($value, $index)
{
 if($index < 0)
  this.unshift($value);
 else if($index >= this.length)
  this.push($value);
 else
  this.splice($index, 0, $value);
}
/**
* 依照数组的下标来删除成分
*/ 
Array.prototype.removeByIndex=function($n) {  
    if($n<0){ //若是n<0,则不开展其余操作。 
      return this; 
    }else{ 
        return this.slice(0,$n).concat(this.slice($n+1,this.length)); 
    } 
}
//依赖indexOf
Array.prototype.remove = function($value)
{
 var $index = this.indexOf($value);

 

tmp.get; // 3

下边是在此以前日常用的,效能也很好。有一些想hash表的痛感。

 for(i=0;i<len;i++){
  if(i<start|| ires>=delLen) arr[iarr++]=this[i];
  else {
   res[ires++]=this[i];
   if(item&&ires==delLen){
    arr[iarr++]=item;
   }
  } 
 }
 if(item&&ires<delLen) arr[iarr]=item;

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]

a便是二个装进对象,它和b相近,代表二个字符串。它们都可以行使字符串的种种法子,也得以涉足字符串运算。

    for (var k in temp)

Array.prototype.indexOf = function($value)
{
 for(var $i=0; $i<this.length; $i++)
 {
  if(this[$i] == $value)
   return $i;
 }

 

tmp.set;

        temp[arr[i]] = true;

Array.prototype.join = function(separator){
 var i=0,str="";
 while(i<this.length) str+=this[i++]+separator;
 return str;
}

 

能够看看,使用对象key来拍卖数组去重的标题,其实是生龙活虎件相比较劳苦的专业,处理倒霉非常轻易造成结果不正确。而这个标题标根本原因正是因为key在动用时有约束。

js数组去重新二种艺术

//分开增添,关键字shallow copy,假如碰着数组,复制数组中的成分
Array.prototype.concat = function(){
 var i=0;
 while(i<arguments.length){
  if(typeof arguments[i] === 'object'&&typeof arguments[i].splice ==='function' &&!arguments[i].propertyIsEnumerable('length')){
  // NOT SHALLOW COPY BELOW
  // Array.prototype.concat.apply(this,arguments[i++]);
   var j=0;
   while(j<arguments[i].length) this.splice(this.length,0,arguments[i][j++]);
   i++;
  } else{
   this[this.length]=arguments[i++];
  }
 }
 return this;
}

 

其它对象首要指数组、日期、正则表达式等那类在Object基本功上派生出来的靶子。那类对象各自有各自的特殊性,平时必要依照气象来组织剖断方式,决定多少个指标是或不是等于。

    return r;

Array.prototype.addAll = function($array)
{
 if($array == null || $array.length == 0)
  return;

 

在做字符串比较的时候,类型的不如会促成结果有后生可畏部分竟然:var a1 = 'a';

Array.prototype.unique3 = function() {
var temp = {}, len = this.length;
for(var i=0; i < len; i++) {
var tmp = this[i];
if(!temp.hasOwnProperty(tmp)) {
temp[this[i]] = "my god";
}
}

 var $tmp = this[$a];
 this[$a] = this[$b];
 this[$b] = $tmp;
}
Array.prototype.max = function() { 
 return Math.max.apply({}, this); 

Array.prototype.min = function() { 
 return Math.min.apply({}, this); 
}
Array.prototype.splice = function(start, delLen, item){
 var len =this.length;
 start = start<0?0:start>len?len:start?start:0;
 delLen=delLen<0?0:delLen>len?len:delLen?delLen:len; 

 

e. Return false.

看起来相当好轻松的吧

Array.prototype.contains = function($value)
{
 for(var $i=0; $i<this.length; $i++)
 {
  var $element = this[$i];
  if($element == $value)
   return true;
 }

 

tmp.set(undefined, 4);

字符串去重方法:

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };
}
if (!Array.prototype.map)
{
  Array.prototype.map = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

方法三(sort)

s.add;

    for (var i in a) { //遍历对象,把已标志的回复成数组
        this[data.length] = i;
    }
    return data;
}

function unique(arr){
    var res =[];
    for(var i=0,len=arr.length;i<len;i++){
        var obj = arr[i];
        if(res.indexOf(obj)===-1) res.push(obj);
    }
    return res;
}
var arr=[1,1,'2','1',3,4]
arr = unique(arr);
console.log(arr);// arr=[1,'2','1',3,4]

本文由胜博发-前端发布,转载请注明来源:会用ES5里面数组的indexOf()方法sbf282.com:,复制代