我该如何对ES6中的`Set`进行排序?

133

new Set(['b', 'a', 'c']).sort()抛出TypeError:set.sort不是一个函数。如何对Set进行排序以确保特定的迭代顺序?


11
集合是无序的。 - SLaks
5
@SLaks也许这样,但我希望能够利用Set提供的唯一键的好处,同时仍然能够对元素进行排序。Java提供了SortedSet,我只能假设他们这样做是因为有人提供了一个有效的用例...ES6不应该成为Java,但对集合进行排序似乎很有用。 - ericsoco
1
你也不能对 SortedSet 使用 sort() 方法。它使用一种树结构,允许按顺序遍历,但是你不能像 ArrayList 一样更改这个排序。如果你想改变顺序,请使用列表。 - Has QUIT--Anony-Mousse
1
可能需要一些研究,但我认为 Set 会保留顺序 new Set(['b', 'a', 'c'].sort()). - Slai
@Slai https://www.ecma-international.org/ecma-262/9.0/index.html#sec-set-objects 我找不到任何关于元素顺序的声明。 - ceving
显示剩余3条评论
4个回答

215

集合不是一个有序的抽象数据结构。

然而,Set 总是有相同的迭代顺序 - 元素插入顺序[1],因此当您通过迭代方法、调用 Symbol.iterator 或使用 for.. of 循环来遍历它时,您总可以期望这个顺序。

您始终可以将集合转换为数组并对其进行排序。

Array.from(new Set(["b","a","c"])).sort();
[...(new Set(["b","a","c"]))].sort(); // with spread.

[1] forEachCreateSetIterator


2
删除了与此相同的答案,但会添加我的评论:“我真的希望有人能提供一个不需要从Set转换为Array再返回的答案。这似乎非常低效。” - ericsoco
15
@ericsoco,ECMAScript规范没有指定OrderedSet,但类似的数据结构在多种其他语言中存在 - 通常通过树来实现。您可以使用用户自定义集合库,即流行的ImmutableJS提供了OrderedSet。实际上,在许多情况下,这可能更有效率。因此,如果您有包含超过100,000个元素的集合 - 我肯定会考虑使用有序的集合实现。 - Benjamin Gruenbaum
9
请注意,对于一组数字,您需要给出一个比较函数来进行排序:(x, y) => x - y。否则,您的数字将按字典顺序排序。 - neo
2
@BenjaminGruenbaum:我认为你误解了一些东西;根据其文档,Immutable.js的OrderedSet使用插入顺序作为迭代顺序;也就是说,它做的与您回答中标准的Set所做的相同。 - ruakh
4
@ruakh 然而,一个 ImmutableJS 的 OrderedSet 对象确实允许你对其内容进行 sort() 排序,这是标准的 Set 所不具备的功能,也是 OP 想要的功能。 - Jamie Ridding
显示剩余2条评论

2
在某些情况下,将集合“排序”到原地可能更可取,类似于array.sort(),可以这样做:
function sortSet(set) {
  const entries = [];
  for (const member of set) {
    entries.push(member);
  }
  set.clear();
  for (const entry of entries.sort()) {
    set.add(entry);
  }
  return set;
};

sortSet(new Set([3,2,1]))
// => Set(3) { 1, 2, 3 }

0

.sort函数是一种高阶函数,这意味着它可以包含另一个函数。首先,只有.sort()可以用于字符或字符串,但对于数字会出现错误。我在视频中讨论了集合以及sort函数。希望你能理解。https://www.youtube.com/watch?v=ztw4Gh8eogw

//This is sort() for getting numbers in ascending order:
const setC = new Set(([58,12,11,10,5,32]).sort((a,b)=>a -b));
//This is sort() for getting numbers in descending order:
const setC = new Set(([58,12,11,10,5,32]).sort((a,b)=>b -a));
//This is sort() for strings
const setD=new Set((['mangoes','bananas', 'apples','oranages']).sort());
// This is sort() for characters
const setD=new Set((['m', 'b', 'a', 'r']).sort());
You can convert the set to an array too and then sort it but that is not 
required in your case.
const arrayofsetA = Array.from(setA);
//for strings or characters
arrayofsetA.sort();
//for numbers or floating point numbers
arrayofsetA.sort((a,b) => a-b);

0

最简单的方法是这样做。

console.log(new Set(['b', 'a', 'c'].sort()))
//Set(3) {"a", "b", "c"}

根据问题,他的目标是保留集合中迭代的顺序。在Set中排序项目并非必要。 - Taimoor Qureshi

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