How to get the first element of Set in ES6 ( EcmaScript 2015)
Asked Answered
T

9

128

In ES6, how do we quickly get the element?

in MDN Syntax for Set, I didn't find an answer for it.

Tricornered answered 12/9, 2015 at 13:25 Comment(2)
What do you consider the "first"?Alow
"Set objects are collections of values. You can iterate through the elements of a set in insertion order." - developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Heffernan
L
143

They don't seem to expose the List to be accessible from the instanced Object. This is from the EcmaScript Draft:

23.2.4 Properties of Set Instances

Set instances are ordinary objects that inherit properties from the Set prototype. Set instances also have a [[SetData]] internal slot.

[[SetData]] is the list of values the Set is holding.

A possible solution (and a somewhat expensive one) is to grab an iterator and then call next() for the first value:

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

Worth mentioning too:

Set.prototype.values === Set.prototype.keys
Lifeguard answered 12/9, 2015 at 14:28 Comment(11)
Btw, iterators are considered pretty inexpensive, that approach is quite optimal…Alow
Not saying iterators are suboptimal or expensive, is just that if you got to create an iterator just to grab a hold of the first element of the list, then that sounds expensive, as opposed to just access the element directly.Lifeguard
or in one line theset.values().next().valueGulp
Why javascript does not provide a method for finding a specific element within the set? Is there any reasonable reason for that?Unprincipled
@AZSH there is a way to find a specific element in a javascript set. It's theset.has(x). What you can't do in a set is retrieve an item by index, since sets are unordered. What javascript is missing is a way to retrieve any item from a set easily. That's what this answer is trying to provide.Scleroderma
Sets actually are ordered. The documentation mentions multiple times that you can integrate over the values/entries in insertion order. Since sets internally keep this knowledge, it would be nice if you could easily get item at index n.Canso
Another one-liner: [...theSet][0]Helga
If you want to use this with all your sets then you can do: Set.prototype.first = function(){return this.values().next().value;}; after this: anyset.first() will give you the first elementSoane
Another nice one, using array destructuring: const [first] = theSet;Mussorgsky
A little bit of experimental performance data. Method 1: first = set.values().next().value. Method 2: first = [...set][0]. Method 3: [first] = set. Methods 1 and 3 are basically O(1) (about 15 million iterations per second in chrome, 1.5 million in firefox regardless of set size). Method 2 is O(n), scaling with n along a ratio at roughly 1s / 300'000'000 for chrome and 10 times slower for firefox. Don't use Method 2 (first = [...set][0]) unless your sets are very very small: it's much costlier than the other methods.Lema
@Canso Sets keeping insertion order does not mean that sets keep their elements in an indexed structure - especially given an O(1) delete operation. Getting item at index n would quite likely have O(n) time complexity.Alow
P
26

there are many solutions

  1. for...of loop

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
  1. ...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);
  1. iterator & next()

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

refs

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

Pompey answered 8/8, 2022 at 17:0 Comment(4)
Result of operation 2. is a set, not just the value.Hg
@Hg Have you tried running my code snippet? It's the number type value in my solution 2.Pompey
Why the if in the for loop?Alow
The spread operator to convert the whole thing into an array is very inefficient.Alow
T
7

succinct

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

console.log(head)

simplified from @rodo's version

functional programming languages use head for the first elements in collections, some will prefer first.

Treasury answered 3/7, 2023 at 12:35 Comment(0)
W
3

A more direct way to get the first element from a Set (works for arrays too):

const mySet = new Set(['foo', 'bar', 'baz'])
const [firstElement, secondElement, thirdElement] = mySet

console.log(thirdElement, firstElement, secondElement) // baz foo bar
Wikiup answered 2/6, 2022 at 9:41 Comment(1)
The most simple and elegant by far! Not to mention that it keeps the type in TypeScript, compared to the iterator solutions which results in any.Ehrman
B
2

The most elegant and practical solution I have found is by retrieving the first IteratorResult and acquiring its value 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
Blatant answered 4/7, 2022 at 13:26 Comment(0)
O
2

most simple way:

const data=new Set(['1', '2', '3']);

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

Orate answered 14/8, 2023 at 10:14 Comment(0)
C
1

Using spread syntax (...):

const mySet = new Set([1, 2, 3, 4, 5]);
const firstElement = [...mySet][0];
console.log(firstElement); // Output: 1

Use destructuring

const set = new Set([1, 2, 3]);
const [first] = set;
console.log(first); // Output: 1

const set = new Set([1, 2, 3]);

const [, second] = set;
console.log(second); // 2

Using Set.values():

const mySet = new Set([1, 2, 3, 4, 5]);
const firstElement = mySet.values().next().value;
console.log(firstElement); // Output: 1

Using for...of loop:

const mySet = new Set([1, 2, 3, 4, 5]);
let firstElement;
for (const element of mySet) {
    firstElement = element;
    break;
}
console.log(firstElement); // Output: 1
Crimson answered 6/3 at 13:2 Comment(0)
A
0

Another choice will be to use the for..of loop like so:

const mySet = new Set(["one", "two", 3]);
for (let item of mySet) {
    console.log(item);
    break;
}
Armoire answered 22/2, 2022 at 15:5 Comment(0)
L
0

The best way is to use the iterator on the Set<T>:

const mySet = new Set<string>(['one', 'two', 'three']);
const firstValue = mySet.values().next().value;
console.log(firstValue);

You could also covert it to an array and then use normal indexing:

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

The first way is better from a complexity standpoint because it doesn't have to create a new array.

Lamar answered 29/6, 2022 at 15:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.