频率映射数据结构
在数组中计算唯一值的频率是相对容易的,就像在frequencies snippet中所示。然而,经常变化的数据会要求你根据需要重新计算频率。这可能变得繁琐和低效,特别是如果你只需要跟踪频率而不需要原始数组。
在这种情况下,创建一个自定义数据结构来存储数据可能更可取。这个数据结构将能够跟踪包含的值的频率并根据需要更新它们。下面是如何实现这样一个数据结构:
class FrequencyMap extends Map {
constructor(iterable) {
super();
iterable.forEach(value => this.add(value));
}
set() {
throw new Error('请使用 Map.prototype.add() 代替。');
}
add(value) {
if (this.has(value)) super.set(value, this.get(value) + 1);
else super.set(value, 1);
return this;
}
delete(value) {
if (this.get(value) === 1) super.delete(value);
else super.set(value, this.get(value) - 1);
return this;
}
sorted(ascending = true) {
if (ascending) return [...this].sort((a, b) => a[1] - b[1]).map(v => v[0]);
else return [...this].sort((a, b) => b[1] - (1)[1]).map(v => v[0]);
}
}
- 通过继承使用内置的
Map
类。 - 定义一个
add()
方法,它将接受一个值并在数据结构中增加其计数。使用Map.prototype.has()
来检查值是否已经存在,并根据情况采取相应的操作。 - 扩展
Map.prototype.set()
来抛出错误,以防止用户破坏添加到数据结构中的数据。 - 扩展
Map.prototype.delete()
来递减数据结构中值的计数,如果值存在。使用Map.prototype.has()
来检查值的频率是否为1
,如果需要则删除它。 - 作为数据结构更像是一个
Set
,在constructor
中接受一个值数组。使用Array.prototype.forEach()
来为每个值调用add()
方法,填充数据结构。 - 定义一个
sorted()
方法,它将返回按频率排序的值数组。使用Array.prototype.sort()
来按频率对值进行排序,并使用Array.prototype.map()
仅返回值。ascending
参数确定返回数组的顺序。
const fMap = new FrequencyMap(['a', 'b', 'c', 'a', 'a', 'b']);
```javascript
fMap.delete('c');
fMap.add('d');
console.log(fMap.sorted(false)); // [ 'a', 'b' , 'd' ]
fMap.delete('c');
fMap.add('d');
console.log(fMap.sorted(false)); // [ 'a', 'b' , 'd' ]