gpt4 book ai didi

javascript - 如何在 JavaScript 中声明默认值为 0 的 Hash.new(0) 来计数对象?

转载 作者:太空宇宙 更新时间:2023-11-03 17:42:16 24 4
gpt4 key购买 nike

我正在尝试遍历数字数组并计算每个数字在数组中出现的次数。

在 ruby​​ 中这很容易,我只需声明一个 Hash.new(0) 并且已经设置了该散列以从 0 开始计数作为一个值。例如:

arr = [1,0,0,0,1,0,0,1]
counter = Hash.new(0)
arr.each { |num| counter[num] += 1 } # which gives {1=> 3, 0=> 5}

我想在 JavaScript 中做同样的事情,但是 let counter = {} 给了我 { '0': NaN, '1': NaN }

您知道如何在 JavaScript 中创建与对象相同的哈希吗?

最佳答案

ECMAScript 没有对象中缺失键的默认值 the same way Ruby does for Hashes .但是,您可以使用动态内省(introspection)元编程 来做类似的事情,使用ECMAScript Proxy objects。 :

const defaultValue = 42;
const proxyHandler = {
get: (target, name) => name in target ? target[name] : defaultValue
};
const underlyingObject = {};

const hash = new Proxy(underlyingObject, proxyHandler);

1 in hash
//=> false
1 in underlyingObject
//=> false

hash[1]
//=> 42
underlyingObject[1]
//=> undefined

所以,你可以这样做:

arr.reduce(
(acc, el) => { acc[el]++; return acc },
new Proxy(
{},
{ get: (target, name) => name in target ? target[name] : 0 }
)
)
//=> Proxy [ { '0': 5, '1': 3 }, { get: [Function: get] } ]

但是,这仍然不等同于 Ruby 版本,其中 the keys of the Hash can be arbitrary objectsthe property keys in an ECMAScript object只能是String s 和 Symbol

Ruby Hash 的直接等价物是 ECMAScript Map .

不幸的是,ECMAScript Map 也没有默认值。我们可以使用我们用于对象的相同技巧并创建一个 Proxy,但这会很尴尬,因为我们必须拦截对 get 的访问。 Map 的方法,然后提取参数,调用 has , 等等。

幸运的是,Map 被设计为可子类化:

class DefaultMap extends Map {
constructor(iterable=undefined, defaultValue=undefined) {
super(iterable);
Object.defineProperty(this, "defaultValue", { value: defaultValue });
}

get(key) {
return this.has(key) ? super.get(key) : this.defaultValue;
}
}

const hash = new DefaultMap(undefined, 42);

hash.has(1)
//=> false

hash.get(1)
//=> 42

这允许我们做这样的事情:

arr.reduce(
(acc, el) => acc.set(el, acc.get(el) + 1),
new DefaultMap(undefined, 0)
)
//=> DefaultMap [Map] { 1 => 3, 0 => 5 }

当然,无论如何,一旦我们开始定义我们自己的 Map,我们可能会一直走下去:

class Histogram extends DefaultMap {
constructor(iterator=undefined) {
super(undefined, 0);

if (iterator) {
for (const el of iterator) {
this.set(el);
}
}
}

set(key) {
super.set(key, this.get(key) + 1)
}
}

new Histogram(arr)
//=> Histogram [Map] { 1 => 3, 0 => 5 }

这也证明了一个非常重要的教训:数据结构的选择可以极大地影响算法的复杂性。通过正确选择数据结构(直方图),算法完全消失,我们所做的就是实例化数据结构。

请注意,在 Ruby 中也是如此。 By choosing the right data structure (there are several implementations of a MultiSet floating around the web), your entire algorithm vanishes and all that is left is :

require 'multiset'

Multiset[*arr]
#=> #<Multiset:#5 0, #3 1>

关于javascript - 如何在 JavaScript 中声明默认值为 0 的 Hash.new(0) 来计数对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57643313/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com