admin管理员组文章数量:1278881
I know that JavaScript now has sets, but I wonder if there is something to realize the function of multiSet, or if there is some framework that has the functions of multiset which I really need a lot.
Or I have to code it by myself to do the research of Red-Black Tree?
I know that JavaScript now has sets, but I wonder if there is something to realize the function of multiSet, or if there is some framework that has the functions of multiset which I really need a lot.
Or I have to code it by myself to do the research of Red-Black Tree?
Share Improve this question edited Feb 28, 2018 at 21:14 Francisco 11.5k6 gold badges37 silver badges46 bronze badges asked Aug 21, 2015 at 4:12 hanzichihanzichi 6593 gold badges12 silver badges22 bronze badges 2- 4 @jfriend00 Exactly this search brought me here, following your instructions would create an infinite loop :-) – Konrad Höffner Commented Oct 7, 2017 at 17:10
- You don't need a redblack tree, what you could probably use is a sorted list, binary search, and a operator for merging sorted lists. – Justin Meiners Commented Jun 21, 2021 at 22:47
4 Answers
Reset to default 3There are no built-in multiset structure, but there are some libraries that have such:
- mnemonist →
MultiSet
- TSTL →
TreeMultiSet
Feel free to add your favorite library in this question.
You can build your own multiset using the Builtin map type and numerical values:
class Multiset {
_backing = new Map();
add(value) {
if (this._backing.has(value)) {
this._backing.set(value, 1 + this._backing.get(value));
} else {
this._backing.set(value, 1);
}
}
delete(value) {
if (this._backing.get(value) > 0) {
this._backing.set(value, this._backing.get(value) - 1);
} else {
//do nothing
}
}
get(value) {
if (this._backing.get(value) > 0) {
return this._backing.get(value);
} else {
return 0;
}
}
}
This is an old question, but it came in at the top of my search. I've ended up using lodash (similar to underscore): For example,
_.countBy([1, 2, 1, 4, 4, 1])
gives the result
{ '1': 3, '2': 1, '4': 2 }
this answer from @AlgorithmicCanary provides the right approach, but we can use more of JavaScript's features:
We can define other methods that the native
Set
provides, likeforEach
,clear
,size
,[Symbol.iterator]
. These should treat each of the key's occurrences individually.We could align the methods to fit the
Set
protocol, so that:add
returns the instance, anddelete
returns the success of the deletion, and- the constructor accepts an iterable to populate the MultiSet
We could really delete the Map entry when a count gets to zero, so that the
has
method on the underlying Map returns the expected result.get
can benefit from the??
operator, returning 0 for any key that does not exist.We can use private fields for the map and its size (cardinality).
Code:
class MultiSet {
#size = 0 // Use private fields
#map = new Map
constructor(iterable) { // Argument as the standard Set allows for
for (const value of iterable) this.add(value);
}
add(value) {
this.#map.set(value, (this.#map.get(value) ?? 0) + 1);
this.#size++;
return this; // As the standard Set does
}
delete(value) {
const count = this.#map.get(value);
if (!count) return false;
if (count == 1) this.#map.delete(value);
else this.#map.set(value, count - 1);
this.#size--;
return true; // boolean: as the standard Set does
}
*[Symbol.iterator]() { // Make instance iterable
for (let [key, count] of this.#map) {
while (count-- > 0) yield key;
}
}
forEach(cb, thisArg) {
for (const key of this) cb.call(thisArg, key, key, this);
}
*entries() {
for (const key of this) yield [key, key];
}
get(value) { return this.#map.get(value) ?? 0 }
has(value) { return this.#map.has(value) }
get size() { return this.#size; }
keys() { return this[Symbol.iterator]() }
values() { return this[Symbol.iterator]() }
// Add other Set methods as they bee availabe:
// ...
}
// Demo
const ms = new MultiSet([1, 2, 1, 3, 1, 2]);
console.log("get(1) ==", ms.get(1)); // 3
console.log("has(3) ==", ms.has(3));
console.log("delete(3) ==", ms.delete(3)); // true
console.log("delete(3) ==", ms.delete(3)); // false
console.log("has(3) ==", ms.has(3));
console.log("get(3) ==", ms.get(3));
console.log("get(2) ==", ms.get(2));
console.log("Iteration of keys:")
console.log(...ms);
本文标签: setIs there something like mulitiSet in JavaScriptStack Overflow
版权声明:本文标题:set - Is there something like mulitiSet in JavaScript? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741215621a2359986.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论