简体   繁体   English

Javascript 映射,键中有两个值

[英]Javascript map with two values in the key

I have 3 dropdowns on my page, the options in the 3rd dropdown depend on the choices in the first two dropdowns.我的页面上有 3 个下拉列表,第三个下拉列表中的选项取决于前两个下拉列表中的选项。

So I am wondering if there is a way to implement a map in javaScript with a 2-dimensional key?所以我想知道是否有一种方法可以使用二维键在javaScript中实现地图? Like <Key1, Key2> -> Value .<Key1, Key2> -> Value

I think an easy way is to concatenate two keys into one string.我认为一种简单的方法是将两个键连接成一个字符串。 Is there any way that is more decent?有没有更体面的方法?

Thanks.谢谢。

You could have an object that contains more objects:您可以拥有一个包含更多对象的对象:

var options = {
    'option 1': {
        'option 1.1': [
            'option 1.1.1',
            'option 1.1.2',
            'option 1.1.3',
            'option 1.1.4'
        ],
        'option 1.2': [
            'option 1.2.1',
            /* etc. */
};

Then, you would access the options for the third dropdown as options[firstSelectedValue][secondSelectedValue] .然后,您将访问第三个下拉列表的options[firstSelectedValue][secondSelectedValue]


EDIT: Here's a demo, too , using some new features that you may need to implement if you're browsing using Internet Explorer 8 or lower :)编辑:这也是一个演示,它使用了一些新功能,如果您使用 Internet Explorer 8 或更低版本浏览,则可能需要实现这些功能:)

You can set a key as an array.您可以将键设置为数组。 Just create your array [key1, key2];只需创建您的数组[key1, key2]; Then set that value as your key and relate it to your value.然后将该值设置为您的键并将其与您的值相关联。

obj[[key1,key2]] = "my value";

Here is a jsFiddle http://jsfiddle.net/TwQLW/这是一个 jsFiddle http://jsfiddle.net/TwQLW/

I was looking for a similar data structure, but could not find.我正在寻找类似的数据结构,但找不到。 I have been working with TypeScript, so I have developed a solution using TypeScript.我一直在使用 TypeScript,所以我开发了一个使用 TypeScript 的解决方案。

export class TwoMapKey<T> {
    private __map__: object;

    constructor() {
        this.__map__ = new Object();
        this.get = this.get.bind(this);
        this.set = this.set.bind(this);
        this.remove = this.remove.bind(this);
        this.keys = this.keys.bind(this);
        this.nestedKeys = this.nestedKeys.bind(this);
        this.clear = this.clear.bind(this);
    }

    public get(key: string, nestedKey: string): T {
        if (!this.__map__[key] || this.__map__[key] && !this.__map__[key][nestedKey])
            return;

        return this.__map__[key][nestedKey];
    }

    public set(key: string, nestedKey: string, value: T): void {
        if (!this.__map__[key]) {
            this.__map__[key] = new Object();
        }

        Object.defineProperty(this.__map__[key], nestedKey, { value: value, configurable: true, enumerable: true });
    }

    public remove(key, nestedKey): void {
        if (!this.__map__[key]) {
            return;
        }

        delete this.__map__[key][nestedKey];
    }

    public keys(): string[] {
        return Object.getOwnPropertyNames(this.__map__);
    }

    public nestedKeys(): Array<string[]> {
        return Object.getOwnPropertyNames(this.__map__).map(key => Object.keys(this.__map__[key]));
    }

    public clear(): void {
        Object.getOwnPropertyNames(this.__map__).forEach(property => {
            delete this.__map__[property];
        });
    } }

You can simply create a map with two keys as below:您可以简单地创建一个带有两个键的地图,如下所示:

let twoKeyMap = new TwoKeyMap<any>();
twoKeyMap.set('mainKey1', 'nestedKey1', {value: 'value'});

Its not as efficent as a HashMap.它不如 HashMap 有效。 You should be able to convert the same in ES6 or ES5 easily.您应该能够轻松地在 ES6 或 ES5 中转换相同的内容。

What is wrong with concatenating the two keys?连接两个键有什么问题? All you need is to be sure, that the concatenated keys are unique, and I guess that this can easily be achieved by separating the two values with a character that is not used by any of the two keys.您只需要确保连接的键是唯一的,我想这可以通过用两个键中的任何一个都不使用的字符分隔两个值来轻松实现。

I created a generic data structure for this purpose as I had a similar problem:我为此目的创建了一个通用数据结构,因为我遇到了类似的问题:

https://github.com/vikashmadhow/map https://github.com/vikashmadhow/map

I know quite some time has passed since this question was asked;我知道自从提出这个问题以来已经过去了一段时间; hopefully this might be of help to others.希望这可能对其他人有所帮助。

You can achieve this by adding the two keys as a key array on a hash object using ES6 syntax.您可以通过使用 ES6 语法将两个键添加为哈希对象上的键数组来实现这一点。 Then you can search using array filter and regular expression:然后您可以使用数组过滤器和正则表达式进行搜索:

const key1 = "key1";
const key2 = "key2";
const value = "whatever";

const hashObject = {};
const firstEntry = [key1, key2];
const secondEntry = [key2, key1];
const entryValue = { value };

hashObject[firstEntry] = entryValue;
hashObject[secondEntry] = entryValue;

const regByFirstKey = new RegExp(`${key1},.`);
const regBySecondKey = new RegExp(`.,${key2}`);

const keysArray = Object.keys(hashObject);

const resultByFirstKey = (keysArray.filter((key) => regByFirstKey.test(key)))[0];
const resultBySecondKey = (keysArray.filter((key) => regBySecondKey.test(key)))[0];

resultByFirstKey ? console.log(hashObject[resultByFirstKey].value) : undefined;
resultBySecondKey ? console.log(hashObject[resultBySecondKey].value) : undefined;

There is no other way.没有其他办法。 JS map is plain object, so the key the same as property name. JS map 是普通对象,所以 key 和 property name 相同。 Even if you try to use eg.即使您尝试使用例如。 array as a key, it'll be converted to string.数组作为键,它将被转换为字符串。 You should concat this string with some special char between or store values in array, and scan it on every access.您应该将这个字符串与一些特殊的字符连接起来,或者将值存储在数组中,并在每次访问时扫描它。

/**
 * type Keys = 'key1' | 'key2';
 * const twoKeysMap = new Map<Keys, number>();    
 */
const twoKeysMap = new Map<'key1' | 'key2', number>();

twoKeysMap.set('key1', 1); // -> ok
twoKeysMap.set('key2', 2); // -> ok
twoKeysMap.set('key3', 3); // -> error

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM