【译】Array与Set的异同及使用场景
栏目: JavaScript · 发布时间: 5年前
内容简介:PS:原文只介绍了Array和Set的一些简单操作,详细API放在文章底部。每一个使用JavaScript编程的人都应该对Array非常熟悉。 通常,我们可以这样形容它:数组是表示一种储存在连续空间中的结构类型(内容可以为number,object等)。 例如:而Set更像是一种抽象的数据类型。它只包含不同的元素/对象,不需要连续分配存储空间。 例如:
PS:原文只介绍了Array和Set的一些简单操作,详细API放在文章底部。
每一个使用JavaScript编程的人都应该对Array非常熟悉。 通常,我们可以这样形容它:数组是表示一种储存在连续空间中的结构类型(内容可以为number,object等)。
例如: [1, 2, 3, 4, 5]
而Set更像是一种抽象的数据类型。它只包含不同的元素/对象,不需要连续分配存储空间。
例如: {1, 2, 3}
它们之间最大的差别就是 Array中的元素是可以重复的,而Set中的元素不可重复 。除此之外,Array被认为是一种索引集合,而Set是一种键的集合。
索引集合是指按下标作为索引值 排序 的数据结构
键的集合使用key访问元素,访问顺序与元素插入顺序一致。
很简单对吧?现在可能有人会问,既然这两者如此不同,为什么还要将它们进行比较?
在编程时,我们可以使用Array或Set来存储相同的数据集。但根据使用情况,我们应该 选用正确的数据结构以助于提供最佳的解决方案 。为了实现这个目标,首先我们需要了解它们分别是什么,有什么特点和能力。前面的文章中我们对这两种数据结构已经有了初步的了解,接下来就来看看它们的构建方式。
如何构建
Array
数组的构建非常简单直接,在JS中声明一个数组你可以直接使用字面上的语法:
var arr = []; //空数组 var arr = [1,2,3]; //元素为1,2,3的数组 复制代码
或者使用构造函数:
var arr = new Array(); //空数组 var arr = new Array(1,2,3);//元素为1,2,3的数组 复制代码
甚至这种更酷的方法:
var arr = Array.from("123"); //["1","2","3"] 复制代码
注:一条建议——除了非用不可的情况尽量不要使用 new Array()
,原因如下:
-
new Array()
的性能比[]
慢很多 -
[]
节约更多输入的时间 - 你可能会犯一些经典的错误,比如:
var arr1 = new Array(10); //长度为10,每个元素都为undefined var arr2 = [10]; // arr2[0] = 10 且 arr2.length = 1; var arr3 = new Array(1,2,3); //[1,2,3] var arr4 = [1,2,3];//[1,2,3] 复制代码
所以,尽量保持一个原则——简单化
Set
Set使用内置的构造函数初始化,没有其它简便的方法。
Set([iterable])
想要创建一个 Set
,需要使用 new
方法,例如:
var emptySet = new Set(); var exampleSet = new Set([1,2,3]); 复制代码
不能使用如下方式:
new Set(1); 复制代码
Set接收一个可遍历的对象作为其输入参数,并将遍历元素依次作为Set中的元素生成对象。因此,我们可以通过数组作为参数去创建Set——但创建的Set中只包含数组中的非重复元素,如上文提到,Set中元素不可重复。
当然,我们也能通过 Array.from()
方法将Set还原为数组:
var set = new Set([1,2,3]); // {1,2,3} var arr = Array.from(set);//[1,2,3] 复制代码
现在,我们知道了如何构建这两种数据结构,接下来让我们对Array / Set提供的最基本方法进行比较。
访问元素
- 首先Set不支持像Array一样通过索引随机访问元素
console.log(set[0]); //undefined console.log(arr[0]); //1 复制代码
- 更重要的是,因为Array中的数据存储在连续的空间中,所以CPU能够通过预处理操作更快地进行数据访问。因此,与其他类型的抽象数据类型进行比较,访问Array中的元素(按顺序,例如for循环)通常会更快更有效。
-
判断一个元素是否在Set中的语法比判断是否在Array中更简洁。Set:
Set.prototype.has(value)
。Array:Array.prototype.indexOf(value)
。
console.log(set.has(0)); // boolean - false console.log(arr.indexOf(0)); // -1 console.log(set.has(1)); //true console.log(arr.indexOf(1)); //0 复制代码
这意味着在Array中,我们需要额外创建检查元素是否在Array中的条件:
var isExist = arr.indexOf(1) !== -1; 复制代码
注:ES6提供了与 Set.prototype.has()
相似的方法 Array.prototype.includes()
来判断元素是否在数组中,但这个方法并没有广泛地被浏览器支持——比如IE..
插入元素
Array
-
向数组中插入元素可以使用时间复杂度为O(1)的
Array.prototype.push()
方法快速完成——元素将会被插入到数组的末尾。
arr.push(4); //[1,2,3,4] 复制代码
-
或者可以使用时间复杂度为O(n)的
Array.prototype.unshift()
方法实现——元素被插入到数组的头部。
arr.unshift(3); //[3,1,2,3] arr.unshift(5, 6); //[5,6,3,1,2,3] 复制代码
Set
-
只有一个方法可以在Set中插入元素——
Set.prototype.add()
。由于Set需要保持其“元素不可重复”的特性,所以每次调用add()
方法,Set都需要便利所有元素以确保无重复元素,通常情况下add()
方法的时间复杂度应为O(n)。不过Set的内部采用哈希表的实现方式,因此可以达到O(1)的时间复杂度。
set.add(3); //{1,2,3} set.add(4); //{1,2,3,4} 复制代码
删除元素
Array
- 使数组如此受欢迎的原因之一是它提供了许多不同的方法去删除元素,例如:
var arr = [5, 6, 1, 2, 3, 4] 复制代码
pop()
——删除并返回最后一个元素,时间复杂度O(1)
arr.pop();//return 4, [5,6,1,2,3] 复制代码
shift()
——删除并返回第一个元素,时间复杂度O(n)
arr.shift(); //return 5; [6,1,2,3] 复制代码
splice(index, delectCount)
——删除从index开始的delectCount个元素。时间复杂度为O(n)
arr.splice(0,1); //[1,2,3] 复制代码
Set
var set = new Set([1, 2, 3, 4]); 复制代码
delete(element)
——删除指定的element
set.delete(4); //{1,2,3} 复制代码
clear()
——清空Set中所有元素
set.clear(); //{} 复制代码
Array并未提供原生方法删除指定元素,我们需要借助其它方法找到元素对应下标,通过 splice()
删除,而Set可以直接使用 delete()
进行删除。
另外,对比Set只提供了一些基本的操作数据的方法,Array提供了更多实用的原生方法( reduce()
, map()
, sort()
等),所以有些人可能会想,为什么我们比起Array会更喜欢Set?
Array和Set的应用场景
delete()
结论
总之,就我而言对比Array,Set并没有明显优势,除了在特定场景中,例如当我们想要以最小成本维护不重复的数据,或者使用到大量不同的数据集时只需要使用最基本的集合操作而无需直接访问元素。
否则,Array通常是更好的选择。因为在需要时获取元素更节省CPU工作量。
欢迎讨论。
其他资料链接:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【译】Object与Map的异同及使用场景
- C++/Golang的数组类型异同
- DevOps与敏捷异同 - DZone DevOps
- Dart 入门 & 与 ts 类型系统的异同
- 浅谈集群、分布式、微服务的异同
- 服务容错模式:舱壁模式、熔断器的异同点
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。