如何在ES6(EcmaScript 2015)中获取Set的第一个元素?

114

在ES6中,我们如何快速获取元素?

MDN Set语法中,我没有找到答案。


5
你认为什么是“第一”? - Bergi
1
Set 对象是值的集合。您可以按插入顺序迭代集合中的元素。 - tonethar
8个回答

137

它们似乎没有将列表公开为可从实例化对象访问的。以下是来自EcmaScript草案的内容:

23.2.4 Set实例的属性

Set实例是普通对象,继承自Set原型的属性。Set实例还有一个[[SetData]]内部插槽。

[[SetData]]是Set所持有的值的列表。

一种可能的解决方案(并且是一种相对昂贵的解决方案)是获取迭代器,然后调用next()以获取第一个值:

var x = new Set();
x.add(1);
x.add({ a: 2 });
//get iterator:
var it = x.values();
//get first entry:
var first = it.next();
//get value out of the iterator entry:
var value = first.value;
console.log(value); //1

值得一提的是:

Set.prototype.values === Set.prototype.keys

11
顺便说一句,迭代器被认为是非常昂贵的,那种方法是相当优化的... - Bergi
3
并不是说迭代器效率低或开销大,只是如果你必须创建一个迭代器来获取列表的第一个元素,那听起来就比直接访问该元素要昂贵。 - MinusFour
69
这句话的翻译是:或者用一行代码实现这个集合中的第一个值。 - kofifus
20
另一个一行代码:[...theSet][0] - Alexandru Savin
19
一些实验性能数据。方法1:first = set.values().next().value。方法2:first = [...set][0]。方法3:[first] = set。方法1和3基本上是O(1)的(在chrome中每秒约1500万次迭代,在firefox中为150万次,不考虑集合大小)。方法2是O(n),随着n的增加呈比例关系,大约为Chrome中的1秒/ 3亿和Firefox中慢10倍。除非集合非常小,否则不要使用方法2(first = [...set][0]):它比其他方法昂贵得多。 - NicolasB
显示剩余6条评论

21
有很多解决方案:
1. 使用for...of循环。

const set = new Set();
set.add(2);
set.add(3);

// return the first item of Set ✅
function getFirstItemOfSet(set) {
  for(let item of set) {
    if(item) {
       return item;
    }   
  }
  return undefined;
}

const first = getFirstItemOfSet(set);
console.log('first item =', first);

  1. destructuring assignment

const set = new Set();
set.add(2);
set.add(3);

// only get the first item ✅
const [first] = set;
console.log('first item =', first, typeof first);
// first item = 2 number

3. 扩展运算符(spread operator)

const set = new Set();
set.add(2);
set.add(3);

// convert Set to Array ✅
const first = [...set][0];
console.log('first item =', first);

4. iteratornext()

const set = new Set();
set.add(2);
set.add(3);

// iterator ✅
const first = set.keys().next().value;
console.log(`first item =`, first);

// OR
set.values().next().value;

// OR
set.entries().next().value[0];
// OR
set.entries().next().value[1];

参考文献

https://www.cnblogs.com/xgqfrms/p/16564519.html


操作2的结果是一个集合,不仅仅是一个值。 - randomuser
@randomuser 你试过运行我的代码片段吗?它是解决方案2中的数值类型值。 - xgqfrms
为什么在for循环中使用if条件语句? - Bergi
扩展运算符将整个内容转换为数组非常低效。 - Bergi

4

let s = new Set([2,3,4])

let [head] = s

console.log(head)

简化自@rodo的版本

2
最简单的方法:
const data=new Set(['1', '2', '3']);

const first = [...data][0];


1
我发现最优雅、最实用的解决方案是通过获取第一个IteratorResult并获取其值set.values().next().value
const set = new Set([0, 1, 2, 3, 4]);   
const first = set.values().next().value; // first will be equal to 0

1
从Set中获取第一个元素的更直接方法(对于数组也适用):
const mySet = new Set(['foo', 'bar', 'baz'])
const [firstElement, secondElement, thirdElement] = mySet

console.log(thirdElement, firstElement, secondElement) // baz foo bar

0
另一个选择是使用for..of循环,例如:
const mySet = new Set(["one", "two", 3]);
for (let item of mySet) {
    console.log(item);
    break;
}

0
最好的方法是在 Set<T> 上使用迭代器:
const mySet = new Set<string>(['one', 'two', 'three']);
const firstValue = mySet.values().next().value;
console.log(firstValue);

您还可以将其转换为数组,然后使用普通索引:

const mySet = new Set<string>(['one', 'two', 'three']);
const firstValue = Array.from(mySet)[0];
console.log(firstValue);

从复杂度的角度来看,第一种方法更好,因为它不需要创建一个新的数组。


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