如何将Set转换为Array?

845

Set似乎是创建保证唯一元素的数组的好方法,但它不公开任何好的获取属性的方式,除了生成器[Set].values之外,该生成器的调用方式很尴尬,即mySet.values.next()

如果您可以在集合上调用map和类似函数,那么这将是可以接受的。 但是您也不能这样做。

我尝试过Array.from,但似乎只能将类似数组(NodeList和TypedArrays?)对象转换为数组。 另一个尝试:Object.keys对于Set无效,而Set.prototype没有类似的静态方法。

所以问题是:是否有任何方便的内置方法可用于创建具有给定Set值的数组?(元素顺序并不重要)。

如果不存在这样的选项,那么可能有一个漂亮的惯用法一行代码来完成它吗?例如,使用for...of或类似方法?


2
亲爱的ESNext/ECMAScript开发者们,没有理由不在Map/Set上使用filter/map/reduce,谢谢 :) - Alexander Mills
13个回答

1455
如果没有这样的选项,那么也许有一个很好的成语化的一行代码可以做到这一点?例如使用for...of或类似方法吗?
实际上,有几种方法可以将Set转换为Array:

注意:对于TypeScript更安全。

const array = Array.from(mySet);

注意:在使用TypeScript编译时,扩展Set存在问题(请参见issue #8856)。最好使用上面的Array.from

const array = [...mySet];
  • 老式的方法是遍历并推送到一个新数组中(Set有forEach):
const array = [];
mySet.forEach(v => array.push(v));
  • 之前,使用非标准的、现在已弃用的数组推导式语法:
const array = [v for (v of mySet)];

2
var array = [v for (v of mySet)]; 在 [tag:Chrome] 46 中无法工作。 - Eric
1
看起来Chrome从45版本开始支持。请参考以下链接: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/from#AutoCompatibilityTable - amwinter
哪种方式更好? - Vic
23
想要补充说明的是,当使用Typescript编译[...mySet]时存在问题(请参见此问题)。因此,如果你打算在不久的将来转换为Typescript,最好使用Array.from(mySet)以保证安全。 - Ivan Gozali
6
顺便提一下,如果有人关心速度问题,以下是从快到慢的排名:第一,老式(forEach/for of);第二,Array.from(稍慢约5%);第三,扩展运算符(稍慢约12%)。 - Cezar D.
显示剩余4条评论

99

3
请参考 https://kangax.github.io/compat-table/es6/ 获取相对较新的支持情况表。目前,在所有桌面浏览器中,只有 Firefox 和 IE TP(又名 Spartan,又名 MS 非 IE 浏览器)支持 Array.from... - c69
зңӢиө·жқҘFirefoxжҳҜе”ҜдёҖж”ҜжҢҒArray.fromзҡ„жөҸи§ҲеҷЁгҖӮhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from - 425nesp
1
在这里,您可以为Chrome启用它 chrome://flags/#enable-javascript-harmony。请记住,这是实验性的,不要认为这是开发的好解决方案。 - sospedra
如果我的集合是对象,使用spread语法会克隆集合还是保留对象引用?(我想调用这些对象的方法,所以我需要它们保持相同,而不是克隆) - Juan Perez

18

假设您只是暂时使用 Set 来获取数组中的唯一值,然后转换回数组,请尝试使用以下代码:

_.uniq([])

这需要使用 underscorelo-dash


不幸的是,唯一的跨浏览器解决方案。 - Marco Sulla

11

也许来晚了,但你只需要按照以下步骤进行:

const set = new Set(['a', 'b']);
const values = set.values();
const array = Array.from(values);

如果浏览器支持ES6或者您使用正确的填充程序(shim)来模拟上述功能,那么这应该可以毫无问题地工作。

编辑: 今天您可以使用@c69建议的方式:

const set = new Set(['a', 'b']);
const array = [...set]; // or Array.from(set)

1
使用 set.entries() 看起来会得到一组键值对的数组。你可以使用 set.values() 得到纯数组。 - Shimon Rachlenko
@ShimonRachlenko 是的,用户确实要求了这一点。 - Roland
5
你可以使用 var array = Array.from(set); - Buffalo
这个答案是错误的。你不需要调用.entries或者.values。正如@Buffalo在上面提到的 - Array.from(set)就足够了。 - c69
1
@c69 这是真的。在回答时,Array.from()并没有按预期工作。但现在,展开运算符和Array.from()都可以正常工作了。 - Roland

6
使用展开运算符获取您想要的结果。
var arrayFromSet = [...set];

1
“最简单的答案:只需在方括号内展开集合。”
let mySet = new Set()
mySet.add(1)
mySet.add(5)
mySet.add(5) 
let arr = [...mySet ]

结果:[1,5]

1
以下代码从一个数组中创建一个集合,然后使用...运算符。
var arr=[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,];
var set=new Set(arr);
let setarr=[...set];
console.log(setarr);

2
这是什么? - ZF007
这被称为扩展语法,实际上是两个不同的操作:(1) 在对象中 (2) 数组/函数参数列表中。后者遵循"迭代协议":它调用Symbol.iterator方法,然后执行整个next()过程。另外,...也出现在两个类似的解构赋值语法中。 - Beni Cherniavsky-Paskin

0

0

做这件事的简单方法

 const array = [...new Set([1,1,2,3,3,4,5])]
    console.log(array)

0

使用Set并将其转换为数组与复制数组非常相似...

因此,您可以使用相同的方法来复制数组,在ES6中非常容易。

例如,您可以使用...

想象一下,您有以下Set:

const a = new Set(["Alireza", "Dezfoolian", "is", "a", "developer"]);

您可以简单地使用以下方法进行转换:

const b = [...a];

结果是:

["Alireza", "Dezfoolian", "is", "a", "developer"]

一个数组,现在你可以使用所有可用于数组的方法...

其他常见的做法:

const b = Array.from(a);

或者使用循环,例如:

const b = [];
a.forEach(v => b.push(v));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接