JavaScript 中的哈希表通常通过 `Object` 或者更常用的 `Map` 对象来实现。以下是这两种哈希表结构的一些常用方法:
### Object 方法
虽然 `Object` 可以用作哈希表,但它的键只能是字符串或符号(Symbol)。这里是一些常用的方法:
- `obj[key]`: 用于访问、添加或更新对象属性。
- `delete obj[key]`: 删除对象的某个属性。
- `Object.keys(obj)`: 返回一个由对象自身可枚举属性组成的数组。
- `Object.values(obj)`: 返回一个由对象自身可枚举属性对应的值组成的数组。
- `Object.entries(obj)`: 返回一个由对象自身可枚举属性及其对应值组成的数组。
- `hasOwnProperty(key)`: 检查对象是否具有特定的自有属性(不是继承的)。
### Map 方法
`Map` 是 ES6 引入的一种新的数据结构,它允许任何类型的键,并且保持插入顺序。以下是一些 `Map` 的常用方法:
- `new Map()`: 创建一个新的 Map 实例。
- `map.set(key, value)`: 添加或更新一个键值对。
- `map.get(key)`: 获取与指定键关联的值。
- `map.has(key)`: 检查 Map 中是否存在指定的键。
- `map.delete(key)`: 移除指定键及其关联的值。
- `map.clear()`: 移除 Map 中的所有键值对。
- `map.size`: 返回 Map 中键值对的数量。
- `map.forEach(callback[, thisArg])`: 对每个键值对执行一次提供的函数。
- `map.keys()`: 返回一个新的 Iterator 对象,该对象包含了按照插入顺序所有的键。
- `map.values()`: 返回一个新的 Iterator 对象,该对象包含了按照插入顺序所有的值。
- `map.entries()`: 返回一个新的 Iterator 对象,该对象包含了按照插入顺序所有的 [key, value] 数组。
使用 `Map` 相较于普通对象作为哈希表有几个优势,比如更好的性能(尤其是在大量数据时),以及内置的支持迭代和大小检查等特性。
求两个哈希表(或称为映射、字典)的交集,通常是指找到两个哈希表中键相同且对应的值也相同的项。根据具体需求,你可能只关心键的交集,或者同时关心键和值都匹配的项。下面是两种情况的实现方法:
### 1. 只关心键的交集
如果你只关心两个哈希表中键的交集,而不在乎它们对应的值是否相同,可以这样做:
```javascript
function getKeysIntersection(map1, map2) {
// 将两个Map对象的键转换为Set集合
const keys1 = new Set(map1.keys());
const keys2 = new Set(map2.keys());
// 找到交集
const intersection = new Set([...keys1].filter(key => keys2.has(key)));
return intersection;
}
// 示例使用
const map1 = new Map([['a', 1], ['b', 2], ['c', 3]]);
const map2 = new Map([['b', 4], ['c', 5], ['d', 6]]);
console.log(getKeysIntersection(map1, map2)); // 输出: Set { 'b', 'c' }
```
### 2. 关心键和值都匹配的项
如果你不仅关心键的交集,还要求这些键在两个哈希表中的值也相等,那么你可以这样实现:
```javascript
function getKeyValueIntersection(map1, map2) {
const intersection = new Map();
for (let [key, value] of map1) {
if (map2.has(key) && map2.get(key) === value) {
intersection.set(key, value);
}
}
return intersection;
}
// 示例使用
const map1 = new Map([['a', 1], ['b', 2], ['c', 3]]);
const map2 = new Map([['b', 2], ['c', 3], ['d', 6]]);
console.log(getKeyValueIntersection(map1, map2)); // 输出: Map(2) { 'b' => 2, 'c' => 3 }
```
这两种方法分别适用于不同的场景。第一种方法只返回键的交集,而第二种方法则返回键和值都匹配的项。选择哪种方法取决于你的具体需求。
`Set` 和 `Map` 是 JavaScript 中两种不同的数据结构,它们各自有不同的用途和特性。以下是它们之间的主要区别:
### Set
1. **存储唯一值**:
- `Set` 用于存储唯一的值(无论是原始值还是对象引用),不允许重复项。
2. **无键值对**:
- `Set` 只存储单一的值,而不像 `Map` 那样以键值对的形式存储数据。
3. **迭代顺序**:
- `Set` 的迭代顺序是插入顺序,即元素按照它们被添加到集合中的顺序进行迭代。
4. **常用方法**:
- `add(value)`:向 `Set` 添加一个新元素。
- `delete(value)`:从 `Set` 中移除指定的元素。
- `has(value)`:检查 `Set` 是否包含某个元素。
- `clear()`:移除 `Set` 中的所有元素。
- `size`:返回 `Set` 中元素的数量。
5. **使用场景**:
- 当你需要确保一组数据中没有重复项时,或者当你需要执行数学集合操作(如并集、交集、差集)时,`Set` 是非常有用的。
### Map
1. **键值对映射**:
- `Map` 用于存储键值对,每个键都是唯一的,但可以关联任何类型的值。键可以是任意类型,包括对象、函数或原始值。
2. **保持插入顺序**:
- `Map` 也保持键值对的插入顺序,这意味着当遍历 `Map` 时,你会按照它们被添加的顺序访问键值对。
3. **常用方法**:
- `set(key, value)`:设置键/值对。
- `get(key)`:获取与指定键关联的值。
- `has(key)`:检查 `Map` 是否包含指定的键。
- `delete(key)`:从 `Map` 中移除指定的键及其对应的值。
- `clear()`:移除 `Map` 中的所有键值对。
- `size`:返回 `Map` 中键值对的数量。
4. **使用场景**:
- 当你需要将某些数据与特定的键关联起来,并且这些键可能是复杂的数据类型(如对象或函数)时,`Map` 提供了比对象更强大的功能。此外,`Map` 支持迭代器协议,因此可以直接在 `for...of` 循环中使用。
### 总结
- 使用 `Set` 来处理唯一值的集合,以及执行集合运算。
- 使用 `Map` 来创建键值对映射,尤其是当你需要使用非字符串类型的键时。
选择使用 `Set` 还是 `Map` 应该基于你具体的应用需求。如果你只需要存储一系列不重复的值,那么 `Set` 是更好的选择;如果你需要关联键和值,那么 `Map` 更适合。