如何在 JavaScript 中创建双向映射,或以其他方式交换值?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21070836/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I create a two-way mapping in JavaScript, or some other way to swap out values?
提问by Doorknob
I currently have a need to temporarily swap out values in a JavaScript string, and therefore I will need to have a two-way map/hash thing.
我目前需要临时交换 JavaScript 字符串中的值,因此我需要有一个双向映射/哈希的东西。
For example, let's say I want to change \*
to __asterisk__
(this is just an example, it's not what I'm actually trying to do). I'll have to be able to map *
to __asterisk__
(to swap out the value in the original string), but then I'll also have to be able to map __asterisk__
back to *
(to get the original string back).
例如,假设我想更改\*
为__asterisk__
(这只是一个示例,这不是我真正想要做的)。我必须能够映射*
到__asterisk__
(以换出原始字符串中的值),但是我还必须能够映射__asterisk__
回*
(以取回原始字符串)。
Here's some quick pseudo-ish code of the kind of thing that I'm looking for, so you can understand it better:
这是我正在寻找的那种东西的一些快速伪代码,所以你可以更好地理解它:
var myString = 'this is \* a test';
// ???
var twoWayMap = new TwoWayMap('*' <---> '__asterisk__', '%' <---> '__percent__', ...);
var newString = myString.replace(/\(.)/g, function(m, c) {
return twoWayMap.getKey(c);
});
// newString is now 'this is __asterisk__ a test'
// ... later in the code ...
var oldString = newString.replace(/__([^_]+)__/g, function(m, c) {
return twoWayMap.getValue(c);
});
// oldString is now 'this is * a test'
This is what I've thought about and tried so far:
这是我迄今为止所想和尝试过的:
var twoWayMap = {'*': '__asterisk__', '%': '__percent__', ...};
// getKey would be like this:
twoWayMap[c];
// getValue would be like:
var val; for (var x in twoWayMap) { if (twoWayMap[x] === c) { val = x; break } }
The obvious problem with this is that the way to get by value is much too complicated, and I don't want to have to write out the whole thing every single time I have to reverse lookup.
这样做的明显问题是按值获取的方法太复杂了,我不想每次必须反向查找时都必须写出整个内容。
I just wanted to know: Is there any way to solve this problem without resorting to looping through an object? If not, is there any way to make it easier or cleaner?
我只是想知道:有没有办法解决这个问题而不诉诸循环遍历一个对象?如果没有,有没有办法让它更容易或更干净?
采纳答案by Barmar
Use two objects. One object contains the * -> _asterisk_
mapping, the other object contains _asterisk_ -> *
.
使用两个对象。一个对象包含* -> _asterisk_
映射,另一个对象包含_asterisk_ -> *
。
var forwardMap = {'*': '__asterisk__', '%': '__percent__', ...};
var reverseMap = {};
for (var key in forwardMap) {
if (forwardMap.hasOwnProperty(key)) {
reverseMap[forwardMap[key]] = key;
}
}
回答by Edgar Villegas Alvarado
With an extra internal object for reverse mapping. Best if we add a utility class ;) like this:
带有用于反向映射的额外内部对象。最好我们添加一个实用程序类 ;) 像这样:
function TwoWayMap(map) {
this.map = map;
this.reverseMap = {};
for(var key in map) {
var value = map[key];
this.reverseMap[value] = key;
}
}
TwoWayMap.prototype.get = function(key){ return this.map[key]; };
TwoWayMap.prototype.revGet = function(key){ return this.reverseMap[key]; };
Then you instantiate like this:
然后你像这样实例化:
var twoWayMap = new TwoWayMap({
'*' : '__asterisk__',
'%' : '__percent__',
....
});
Then, for using it:
然后,使用它:
twoWayMap.get('*') //Returns '__asterisk__'
twoWayMap.revGet('__asterisk__') //Returns '*'
EDIT: Equivalent with ES6 syntax
编辑:等效于 ES6 语法
class TwoWayMap {
constructor(map) {
this.map = map;
this.reverseMap = {};
for(let key in map) {
const value = map[key];
this.reverseMap[value] = key;
}
}
get(key) { return this.map[key]; }
revGet(key) { return this.reverseMap[key]; }
}
Usage is the same
用法是一样的
Hope this helps. Cheers
希望这可以帮助。干杯
回答by sparrow
回答by harunurhan
I needed something similar, and created https://www.npmjs.com/package/bi-directional-map
我需要类似的东西,并创建了https://www.npmjs.com/package/bi-directional-map
It is implementing a 2-way map using 2 es6 Map, even though it doesn't have a much functionality, it is tested and since it's written typescript
comes with official typings.
它正在使用 2 es6 Map 实现一个 2-way map,尽管它没有太多功能,但它已经过测试,并且因为它typescript
是用官方类型编写的。
回答by AndyL
Some might prefer a more succinct functional style...
有些人可能更喜欢更简洁的功能风格......
const create2WayMap = (seedMap, mapName, reversemapName) => ({
[mapName]: { ...seedMap },
[reversemapName]: Object.keys(seedMap).reduce((map, key) => {
const value = seedMap[key]
return { ...map, [value]: key }
}, {})
})
usage:
用法:
const myIDMap = create2WayMap(
{
1: 'SomeString',
2: 'Another String',
3: 'Another'
},
'idStrings',
'idNumbers'
)
let id = 2
const str = myIDMap.idStrings[id] // yields 'Another String'
id = myIDMap.idNumbers[str] // yields 2
回答by App-Devon
similar to @harunurhan's answer (but much less verbose) I created a small class that takes in a Typescript Map and generates a readonly two-way map:
类似于@harunurhan 的回答(但不那么冗长)我创建了一个小类,它接受一个 Typescript Map 并生成一个只读的双向映射:
export class TwoWayReadonlyMap<T, K> {
map: Map<T, K>;
reverseMap: Map<K, T>;
constructor(map: Map<T, K>) {
this.map = map;
this.reverseMap = new Map<K, T>();
map.forEach((value, key) => {
this.reverseMap.set(value, key);
});
}
get(key: T) {
return this.map.get(key);
}
revGet(key: K) {
return this.reverseMap.get(key);
}
}