如何通过其值获取JavaScript Map中的键?

时间:2017-11-06 11:13:43

标签: javascript dictionary

我有像这样的js Map

let people = new Map();
people.set('1', 'jhon');
people.set('2', 'jasmein');
people.set('3', 'abdo');

我想要的是一种通过其值返回键的方法

let jhonKey = people.getKey('jhon'); // jhonKey should be '1'

10 个答案:

答案 0 :(得分:17)

你可以在一系列条目中搜索它。

let people = new Map();
people.set('1', 'jhon');
people.set('2', 'jasmein');
people.set('3', 'abdo');

let jhonKeys = [...people.entries()]
        .filter(({ 1: v }) => v === 'jhon')
        .map(([k]) => k);

console.log(jhonKeys); // if empty, no key foudn otherwise all found keys.

答案 1 :(得分:17)

您可以使用for..of循环直接遍历map.entries并获取密钥。



function getByValue(map, searchValue) {
  for (let [key, value] of map.entries()) {
    if (value === searchValue)
      return key;
  }
}

let people = new Map();
people.set('1', 'jhon');
people.set('2', 'jasmein');
people.set('3', 'abdo');

console.log(getByValue(people, 'jhon'))
console.log(getByValue(people, 'abdo'))




答案 2 :(得分:7)

没有直接的方法可以在这个方向上挑选信息,所以如果您拥有的只是地图,则需要按照其他人的建议循环使用该地图。

如果map / array / other足够大以至于这样的循环会出现性能问题并且反向查找的要求在项目中很常见,那么你可以使用一对map / arrays / other来实现自己的结构一个按照当前对象,另一个按键和值反转。这样反向查找与普通查找一样有效。当然,您需要做更多的工作,因为您需要实现作为一个或两个底层对象的传递所需的每个方法,因此如果地图很小和/或不需要反向查找-via-loop选项可能更好,因为维护更简单,并且JiT编译器可能更容易优化。

在任何情况下,要注意的一件事是多个键可能具有相同的值。如果这是可能的,那么在循环遍历地图时,你需要决定是否可以任意返回一个可能的键(可能是第一个),或者如果你想返回一个键数组,并且实现一个反向索引对于可能具有重复值的数据,也需要考虑相同的问题。

答案 3 :(得分:2)

可以将Map反转,以便键是值,而值是键,然后将原始值查找为键。这是一个示例:

let myMap = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

let invertedMap = new Map([...myMap.entries()].map(
  ([key, value]) => ([value, key]))
);

console.log(invertedMap.get('one'))
// => 1

答案 4 :(得分:1)

尽管已经存在较晚的答案和其他一些不错的答案,但是您仍然可以尝试在“ ...”和“ Array.find”下方

let people = new Map();
people.set('1', 'jhon');
people.set('2', 'jasmein');
people.set('3', 'abdo');

function getKey(value) {
  return [...people].find(([key, val]) => val == value)[0]
}

console.log('Jasmein - ',getKey('jasmein'))

console.log('Jhon - ',getKey('jhon'))

答案 5 :(得分:1)

为什么不简单地使用 forEach prototype/instance method 内置的地图遍历地图以寻找目标值?

let jhonKey;
people.forEach((value, key) => {
    if (value === 'jhon')
        jhonKey = key
});

或者更好的,也许是注入原型链/polyfill启发的各种解决方案:

Map.prototype.getKey = function(targetValue){
    let desiredKey;
    this.forEach((value, key) => {
        if (value === targetValue)
            desiredKey = key
    });
    return desiredKey;
}

let people = new Map();
people.set('1', 'jhon');
people.set('2', 'jasmein');
people.set('3', 'abdo');

let jhonKey = people.getKey('jhon');
console.log(`The key for 'jhon' is: ${jhonKey}`);

对于任何好奇我为什么添加另一个答案的人。这些答案中的大多数(例外,我喜欢 Rajesh's answer,但我利用了内置并添加到原型链中)以通过使用扩展运算符或甚至直接制作数组。 Object.keys() 请注意,您的性能也非常差。在偶然发现比我想出的更好的东西后,我对现有的答案并不满意。

如果您特别关心性能,可以考虑使用 this answer 在找到值后打破循环的奖励积分。

答案 6 :(得分:0)

JavaScript MapObject

给出一个JavaScript地图,我喜欢@Nitish答案:

const map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

function getKey(val) {
  return [...map].find(([key, value]) => val === value)[0];
}

console.log(getKey('one'));   // 1
console.log(getKey('two'));   // 2
console.log(getKey('three')); // 3

对于JavaScript对象,您可以执行以下操作:

const map = {
  1: 'one',
  2: 'two',
  3: 'three',
};

function getKey(val) {
  return Object.keys(map).find(key => map[key] === val);
}

console.log(getKey('one'));   // 1
console.log(getKey('two'));   // 2
console.log(getKey('three')); // 3

答案 7 :(得分:0)

我的TypeScript版本:

const getByValue = <A, B>(m: Map<A,B>, searchValue: B):[A, B] | undefined => {
  const l:IterableIterator<[A, B]> = m.entries();
  const a:[A, B][] = Array.from(l);
  return a.find(([_k,v]) => v === searchValue);
}

答案 8 :(得分:0)

JS:

// Returns keys for all instances
function findAll(obj) {
  return Array.from(items.keys()).map(k => items.get(k) === obj ? k : undefined).filter(k => k);
}

// Returns keys for the first instances
function findFirst(obj) {
  return Array.from(items.keys()).find(k => items.get(k) === obj);
}

打字稿:

protected items = new Map<TKey, TObject>();

public findAll(obj: TObject): Array<TKey> {
  return Array.from(this.items.keys()).map(k => this.items.get(k) === obj ? k : undefined).filter(k => !!k);
}

public findFirst(obj: TObject): TKey | undefined {
  return Array.from(this.items.keys()).find(k => this.items.get(k) === obj);
}

说明:

// Gets the keys as an array
Array.from(this.items.keys())

// Map the keys whose object matches the instance of `obj` to the key itself, undefined otherwise
.map(k => this.items.get(k) === obj ? k : undefined)

// Filter out array elements that are undefined
// (!! is for strict type-checking/readability practices, you can simply use k => k)
.filter(k => !!k)

// Finds the first occurrence of the key for the given object, undefined if not found
.find(k => this.items.get(k) === obj)

答案 9 :(得分:-1)

这是一个正确类型的 Typescript 解决方案,它不会不必要地创建数组。

function find_map_value<K, V>(m: Map<K, V>, predicate: (v: V) => boolean): [K, V] | undefined {
  for (const [k, v] of m) {
    if (predicate(v)) {
        return [k, v];
    }
  }
  return undefined;
}