JavaScriptオブジェクトのキーをその値で取得する方法は?


387

私は連想配列として使用する非常に単純なJavaScriptオブジェクトを持っています。値のキーを取得できる単純な関数はありますか、それともオブジェクトを反復して手動で見つける必要がありますか?


これを行うためのそのような標準機能はありません。マッピングが本当に双方向である場合、「反転」マップを作成してインデックスを付けるのは簡単です。それ以外の場合は、単純なプロパティイテレータ(おそらくhasOwnPropertyガードを使用)と関数内に隠されたアーリーリターンがうまく機能します...

オブジェクトが複数のキーによって参照されている場合、これはどのように機能しますか?var o = []; var map = {first: o, second: o}。何がfind_key(o)返りますか?
Gareth

3
関係ありません;)私は、一意のキーと値のペアを持つ配列にのみ使用することを意図していました。
arik


反復なしのバージョンを作成しました。stackoverflow.com/ a / 36705765/696535。jsfiddleですべての提案されたソリューションをテストすることは興味深いでしょう
Pawel

回答:


90

Underscore.jsのライブラリ:

var hash = {
  foo: 1,
  bar: 2
};

(_.invert(hash))[1]; // => 'foo'

384
@GeorgeJempty誰もが単純なキールックアップのために5kbのライブラリをロードすることを望んでいるわけではありません;)
tckmn 2014年

4
値に一致するすべてのキーを取得するソリューションを探している人のための参考までに、これは機能しません。
ブレット

2
下線キーも機能します。underscorejs.org/#keys _.keys({1:1、2:2、3:3}); => ["one"、 "two"、 "three"]
Thaddeus Albers 2014年

1
デフォルトの文字列のシリアル化が衝突するため、値にオブジェクトが含まれている場合、_。invertは機能しません。あなたはこの嫌悪を使うかもしれません:_.chain(hash).pairs().findWhere({1: 1}).value()[0]
DanHorner

3
これは受け入れるべき答えではありません。現在のコード構造の変更を強制するライブラリを介した解決策を提案します
Matteo

593
function getKeyByValue(object, value) {
  return Object.keys(object).find(key => object[key] === value);
}

ES6、プロトタイプの変更または外部ライブラリはありません。

例、

function getKeyByValue(object, value) {
  return Object.keys(object).find(key => object[key] === value);
}


const map = {"first" : "1", "second" : "2"};
console.log(getKeyByValue(map,"2"));


8
まあ、IE11をサポートしていない場合は本当にきれいです:-)もしそうなら、ポリフィルが必要です
Chexpir

4
実装によっては、キーセットを具体化するため、これはおそらくO(n)スペースをkeys()必要とします。
David Ehrmann 2017年

2
きれいだが遅い。
飛行船

4
複数のキーではなく、検索の同じ値の使用フィルタを使用している場合function getKeyByValue(object, value) { return Object.keys(object).filter(key => object[key] === value); }
saketh

笑。これは遅くはありません。O(n)が実行可能な最高のランタイムです。
ベンウェインライト

179

利用できる標準的な方法はありません。反復する必要があり、単純なヘルパーを作成できます。

Object.prototype.getKeyByValue = function( value ) {
    for( var prop in this ) {
        if( this.hasOwnProperty( prop ) ) {
             if( this[ prop ] === value )
                 return prop;
        }
    }
}

var test = {
   key1: 42,
   key2: 'foo'
};

test.getKeyByValue( 42 );  // returns 'key1'

注意点:上記が機能する場合でも、ホストまたはネイティブオブジェクトを拡張することは、一般的にお勧めできません.prototype。それが問題に非常によく合うので、私はここでそれをしました。とにかく、おそらくこの関数をの外で使用.prototypeし、代わりにオブジェクトをそれに渡す必要があります。


2
実際には、for-inループがプロパティチェーンを下るということを知っていても問題ありません。つまり、「for(var key in obj)」が「getKeyByValue」を「キー」としていつか提供するということです。

ああ、私は値が存在しない場合にこれがステルスにundefinedを返す方法が大好きです。よくやった。また、興味深い点として、これはO(n)を実行するので、オブジェクトに大量のプロパティ(大都市の人々とその住所のリストなど)がある場合は、おそらくより効率的な検索が必要になります。たぶん値のソートと二分探索?え?
コービン2013年

どうもありがとうございました。悪い考えを見つけたときまでに、なぜこれを検索して、この回答の拡張と豊富な読み物のためにここに追加したのでしょうか。stackoverflow.com/questions/3085240/...
simongcc

1
@jAndy ===ではなく、==です。コードは===では機能しません。未定義を返します。
デクスター

私はそれを文字列に変換すると、より良いだけで追加、修正型エラーになると思い.toString()のようにobj[ key ].toString()...必要に応じて値とに
CrandellWS

129

言ったように、反復が必要です。たとえば、最新のブラウザでは次のようになります。

var key = Object.keys(obj).filter(function(key) {return obj[key] === value})[0];

どこ value探している値が含まれる。それは、おそらくループを使用するだろうと言いました。

それ以外の場合は、適切な「ハッシュマップ」オブジェクトを使用できます-JSにはいくつかの実装があります-または独自に実装します。

2018年の更新

6年が経過しましたが、私はまだここで投票しています。そのため、コメントだけでなく、回答自体にも最新のブラウザー/環境向けのより最新のソリューションを記載する必要があると思います。

const key = Object.keys(obj).find(key => obj[key] === value);

もちろんそれは関数にすることもできます:

const getKeyByValue = (obj, value) => 
        Object.keys(obj).find(key => obj[key] === value);

18
ES6:Object.keys(obj).or(o=>o[key] === value)
Benjamin Gruenbaum 2013年

残念ながら、矢印機能はまだ「最新の」ブラウザではないため、現時点では少し役に立たない-私はFirefox Nightlyのjetpackで使用しています。Firefox22で使用します。とにかく、or配列のことは知りませんメソッド、そしてそれは私にはここではその目的が明確ではありません:私はいくつかの追加の詳細に感謝します!:)
ZER0 2013年

1
矢については、来て、私はそれを待っています:) or確かに!最近になって評価され、受け入れられました(まだ実装していないと思います)。それが行うことは、述語に一致する配列の最初の要素を見つけてそれを返すことです。だから、[1,2,3,4].or(x=>x>2)戻ってくる3[1,2,3,4,5].or(x=>x<3)返します1。C#のFirstOrDefault :)のようなもの
Benjamin Gruenbaum

ええ、矢印は来ていますが、広く使われる必要があります-私のように、誰かが特定のエンジンに取り組んでいない限り。ES6の新しい提案を知らなかったので、かなり閉鎖されていると思いましたor。この方法に関するリンクはありますか?あなたが言ったことから、それは述語「または」配列自体に一致するアイテムを返すようですか?
ZER0 2013年

1
@ sg552は後で説明するように、or名前が変更されました。今はfindを使うべきだと思います
ZER0 2018

42

lodashの方法https://lodash.com/docs#findKey

var users = {
  'barney':  { 'age': 36, 'active': true },
  'fred':    { 'age': 40, 'active': false },
  'pebbles': { 'age': 1,  'active': true }
};

_.findKey(users, { 'age': 1, 'active': true });
// → 'pebbles'


ロダッシュは明らかにこの問題の最良の解決策です。アンダースコアよりもましだと思います。
arik

4
参考までに、「アンダースコアの方法」:_.findKey(users, { 'age': 1, 'active': true });...それは同じ
craigmichaelmartin

arrayが使用する必要のある値である場合:-let obj = {a:[1、2]、b:[3、4]、c:[5、6]} _.findKey(obj、function(val){ return _.isEqual(val、[5、6]);});
ashishyadaveee11 2016年

8
文字列や整数のように値が単純な場合、期待に反してこれは機能しません。例えば、ここで述べように、あなたがする必要 _.find_key({a: "A", b:"B"}, "B"})があるリターンundefined_.find_key({a: "A", b:"B"}, _.partial(_.isEqual,"B")})
ryan2johnson9

1
@ ryan2johnson9それはロダッシュの私の問題です。一部の機能を理解するのに苦労しています(どうやら私だけです)。しかしとにかく、それはうまくいきます。別の短い解決策を見つけました。大きなオブジェクトにオーバーヒープが発生するため、このオブジェクトには注意してください。_.invert(haystack)[needle]
Empi

33
function extractKeyValue(obj, value) {
    return Object.keys(obj)[Object.values(obj).indexOf(value)];
}

閉鎖コンパイラがコンパイル後に不明になるキー名を抽出するために作成

よりセクシーなバージョンですが、将来のObject.entries機能を使用しています

function objectKeyByValue (obj, val) {
  return Object.entries(obj).find(i => i[1] === val);
}

7
プレーンなJavaScriptを使用しているため、これは2017年以降に最適です。
ブレインバッグ2018

同じ値を持つ2つ以上の数値がある場合は機能しないようです
JuicY_Burrito

@SamuelChenは正しいですが、機能した場合、結果として配列が必要になります。代わりにObject.entries(obj).find(i => i[1] === val);使用する場所filterObject.entries(obj).filter(i => i[1] === val);
パウェル

Object.entries(obj).find( ([ key, value ]) => value === val);
解体

24

ES6 +ワンライナー

let key = Object.keys(obj).find(k=>obj[k]===value);

次の値を持つすべてのキーを返します。

let keys = Object.keys(obj).filter(k=>obj[k]===value);

1
依存関係がないので、受け入れられた答えになるはずです。
アンドリューシュルツ

22

私はこの関数を使用します:

Object.prototype.getKey = function(value){
  for(var key in this){
    if(this[key] == value){
      return key;
    }
  }
  return null;
};

使用法:

// ISO 639: 2-letter codes
var languageCodes = {
  DA: 'Danish',
  DE: 'German',
  DZ: 'Bhutani',
  EL: 'Greek',
  EN: 'English',
  EO: 'Esperanto',
  ES: 'Spanish'
};

var key = languageCodes.getKey('Greek');
console.log(key); // EL

10
+1のきちんとしたソリューション。しかし、私は質問があります:obj.hasOwnProperty(key)この場合、常に確認する必要はありませんか、それとも不要ですか?
V-Light

5
オブジェクトのプロトタイプを変異することは悪い習慣です:stackoverflow.com/questions/23807805/...
ジョンKoops

18

非反復可能ソリューション

主な機能:

var keyByValue = function(value) {

    var kArray = Object.keys(greetings);        // Creating array of keys
    var vArray = Object.values(greetings);      // Creating array of values
    var vIndex = vArray.indexOf(value);         // Finding value index 

    return kArray[vIndex];                      // Returning key by value index
}

キーと値を持つオブジェクト:

var greetings = {
    english   : "hello",
    ukranian  : "привіт"
};

テスト:

keyByValue("привіт");
// => "ukranian"

より簡単: Object.keys(greetings )[Object.values(greetings ).indexOf('привіт')]
Shutsman

16

プロトタイプをクリーンに保ちます。

function val2key(val,array){
    for (var key in array) {
        if(array[key] == val){
            return key;
        }
    }
 return false;
}

例:

var map = {"first" : 1, "second" : 2};
var key = val2key(2,map); /*returns "second"*/

15

あなたが作業している場合はアンダースコアまたはLodashライブラリは、使用することができます_.findKeyの機能を:

var users = {
  'barney':  { 'age': 36, 'active': true },
  'fred':    { 'age': 40, 'active': false },
  'pebbles': { 'age': 1,  'active': true }
};

_.findKey(users, function(o) { return o.age < 40; });
// => 'barney' (iteration order is not guaranteed)

// The `_.matches` iteratee shorthand.
_.findKey(users, { 'age': 1, 'active': true });
// => 'pebbles'

// The `_.matchesProperty` iteratee shorthand.
_.findKey(users, ['active', false]);
// => 'fred'

// The `_.property` iteratee shorthand.
_.findKey(users, 'active');
// => 'barney'

13

私は、強力で柔軟かつ効率的なJavaScript双方向マップインターフェイスを実装するbimapライブラリ(https://github.com/alethes/bimap)を作成しました。これは依存関係がなく、サーバー側(Node.jsではでインストールできますnpm install bimap)とブラウザー(lib / bimap.jsにリンクすること)の両方で使用できます。

基本的な操作は本当に簡単です:

var bimap = new BiMap;
bimap.push("k", "v");
bimap.key("k") // => "v"
bimap.val("v") // => "k"

bimap.push("UK", ["London", "Manchester"]);
bimap.key("UK"); // => ["London", "Manchester"]
bimap.val("London"); // => "UK"
bimap.val("Manchester"); // => "UK"

キーと値のマッピングの取得は、両方向で同等に高速です。コストのかかるオブジェクト/配列トラバーサルは内部に存在しないため、データのサイズに関係なく、平均アクセス時間は一定のままです。


反復を必要としない唯一のソリューションの1つ(ソリューション自体、標準ライブラリ、または別のライブラリのいずれか)。
スコット・ルディガー

6

次は表示されませんでした:

const obj = {
  id: 1,
  name: 'Den'
};

function getKeyByValue(obj, value) {
  return Object.entries(obj).find(([, name]) => value === name);
}

const [ key ] = getKeyByValue(obj, 'Den');
console.log(key)
  


5

値は一意であるため、キーの追加セットとして値を追加できるはずです。これは、次のショートカットで実行できます。

var foo = {};
foo[foo.apple = "an apple"] = "apple";
foo[foo.pear = "a pear"] = "pear";

これにより、キーまたは値を介した取得が可能になります。

var key = "apple";
var value = "an apple";

console.log(foo[value]); // "apple"
console.log(foo[key]); // "an apple"

これは、キーと値の間に共通の要素がないことを前提としています。


すべてのソリューションを参照して、私はこれを使いました。非常に直感的です。
ニーム

1
反復を必要としない唯一のソリューションの1つ(ソリューション自体、標準ライブラリ、または別のライブラリのいずれか)。
スコット・ルディガー

OPは、キーと値のペアはすべて一意であると言っていたため、このローテクな答えは素晴らしいです!よくやった;)
カスタムコマンダー

4

与えられたinput={"a":"x", "b":"y", "c":"x"}...

  • 最初の値を使用するには(例:)output={"x":"a","y":"b"}

input = {
  "a": "x",
  "b": "y",
  "c": "x"
}
output = Object.keys(input).reduceRight(function(accum, key, i) {
  accum[input[key]] = key;
  return accum;
}, {})
console.log(output)

  • 最後の値を使用するには(例:) output={"x":"c","y":"b"}

input = {
  "a": "x",
  "b": "y",
  "c": "x"
}
output = Object.keys(input).reduce(function(accum, key, i) {
  accum[input[key]] = key;
  return accum;
}, {})
console.log(output)

  • 各値のキーの配列を取得するには(例:) output={"x":["c","a"],"y":["b"]}

input = {
  "a": "x",
  "b": "y",
  "c": "x"
}
output = Object.keys(input).reduceRight(function(accum, key, i) {
  accum[input[key]] = (accum[input[key]] || []).concat(key);
  return accum;
}, {})
console.log(output)


1
これは間違いなく最良の答えですが、特定のオブジェクトのキーのみを返す、つまり機能的には配列のindexOfと同じになるように変換する方法に頭を悩ませていました。
Souhaieb Besbes

メモリが制約であり、何度もオブジェクトを調べるために多くの処理能力を費やすことをいとわない場合を除いて、上記の「出力」を変数に保存し、そこで結果を調べるだけです...などoutput['x']。それはあなたが求めていたものですか?
Fabio Beltramini

2

http://jsfiddle.net/rTazZ/2/

var a = new Array(); 
    a.push({"1": "apple", "2": "banana"}); 
    a.push({"3": "coconut", "4": "mango"});

    GetIndexByValue(a, "coconut");

    function GetIndexByValue(arrayName, value) {  
    var keyName = "";
    var index = -1;
    for (var i = 0; i < arrayName.length; i++) { 
       var obj = arrayName[i]; 
            for (var key in obj) {          
                if (obj[key] == value) { 
                    keyName = key; 
                    index = i;
                } 
            } 
        }
        //console.log(index); 
        return index;
    } 

Fr0zenFyr @: -次のリンクは、あなたがより良い質問に答えることができstackoverflow.com/questions/8423493/...
ATUR

2

または、さらに簡単です-キーと値を使用して新しいオブジェクトを作成し、そのオブジェクトに対してルックアップを行います。上記のプロトタイプコードを使用して競合が発生しました。キーの周りにString関数を使用する必要はありません。これはオプションです。

 newLookUpObj = {};
 $.each(oldLookUpObj,function(key,value){
        newLookUpObj[value] = String(key);
    });

2

これはUnderscorejsメソッドの小さな拡張であり、代わりにLodashを使用します。

var getKeyByValue = function(searchValue) {
  return _.findKey(hash, function(hashValue) {
    return searchValue === hashValue;
  });
}

FindKeyは、値に一致する最初のキー検索して返します。
代わりに最後の一致が必要な場合は、代わりに FindLastKeyを使用してください。


2

この質問がパルプに負けていないかのように...

好奇心があなたにもたらすものをここに示します...

オブジェクトに文字列値のみが含まれていると確信している場合は、この実装を思い起こさせるために本当に疲れ果てることができます。

var o = { a: '_A', b: '_B', c: '_C' }
  , json = JSON.stringify(o)
  , split = json.split('')
  , nosj = split.reverse()
  , o2 = nosj.join('');

var reversed = o2.replace(/[{}]+/g, function ($1) { return ({ '{':'}', '}':'{' })[$1]; })
  , object = JSON.parse(reversed)
  , value = '_B'
  , eulav = value.split('').reverse().join('');

console.log('>>', object[eulav]);

たぶんここから構築するのに役立つ何かがあるでしょう...

これがあなたを楽しませるといいのですが。


2

これに対するLodashソリューションは、ネストされたオブジェクトではなく、フラットキー=>値オブジェクトに対して機能します。受け入れられた回答の使用に関する提案_.findKeyことは、ネストされたオブジェクトを持つオブジェクト機能しますが、この一般的な状況では機能しません。

このアプローチでは、オブジェクトを反転させ、キーを値に交換し、新しい(反転された)オブジェクトの値を検索してキーを見つけます。キーが見つからない場合falseはが返されますが、これは優先されundefinedますが、これをの_.getメソッドの3番目のパラメーターで簡単に交換できますgetKey()

// Get an object's key by value
var getKey = function( obj, value ) {
	var inverse = _.invert( obj );
	return _.get( inverse, value, false );
};

// US states used as an example
var states = {
	"AL": "Alabama",
	"AK": "Alaska",
	"AS": "American Samoa",
	"AZ": "Arizona",
	"AR": "Arkansas",
	"CA": "California",
	"CO": "Colorado",
	"CT": "Connecticut",
	"DE": "Delaware",
	"DC": "District Of Columbia",
	"FM": "Federated States Of Micronesia",
	"FL": "Florida",
	"GA": "Georgia",
	"GU": "Guam",
	"HI": "Hawaii",
	"ID": "Idaho",
	"IL": "Illinois",
	"IN": "Indiana",
	"IA": "Iowa",
	"KS": "Kansas",
	"KY": "Kentucky",
	"LA": "Louisiana",
	"ME": "Maine",
	"MH": "Marshall Islands",
	"MD": "Maryland",
	"MA": "Massachusetts",
	"MI": "Michigan",
	"MN": "Minnesota",
	"MS": "Mississippi",
	"MO": "Missouri",
	"MT": "Montana",
	"NE": "Nebraska",
	"NV": "Nevada",
	"NH": "New Hampshire",
	"NJ": "New Jersey",
	"NM": "New Mexico",
	"NY": "New York",
	"NC": "North Carolina",
	"ND": "North Dakota",
	"MP": "Northern Mariana Islands",
	"OH": "Ohio",
	"OK": "Oklahoma",
	"OR": "Oregon",
	"PW": "Palau",
	"PA": "Pennsylvania",
	"PR": "Puerto Rico",
	"RI": "Rhode Island",
	"SC": "South Carolina",
	"SD": "South Dakota",
	"TN": "Tennessee",
	"TX": "Texas",
	"UT": "Utah",
	"VT": "Vermont",
	"VI": "Virgin Islands",
	"VA": "Virginia",
	"WA": "Washington",
	"WV": "West Virginia",
	"WI": "Wisconsin",
	"WY": "Wyoming"
};

console.log( 'The key for "Massachusetts" is "' + getKey( states, 'Massachusetts' ) + '"' );
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


2

これが私の解決策です:

たとえば、3つの値のペアを含むオブジェクトがあるとします。

function findKey(object, value) {

    for (let key in object)
        if (object[key] === value) return key;

    return "key is not found";
}

const object = { id_1: "apple", id_2: "pear", id_3: "peach" };

console.log(findKey(object, "pear"));
//expected output: id_2

オブジェクトと検索するキーの値である2つのパラメーターを取るfindKey(array、value)を記述するだけです。そのため、このメソッドは再利用可能であり、この関数に2つのパラメータを渡すだけで毎回オブジェクトを手動で繰り返す必要はありません。


2

ES6メソッド:

Object.fromEntries(Object.entries(a).map(b => b.reverse()))['value_you_look_for']

0

私は通常、アンダースコアよりもロダッシュをお勧めします。

お持ちの方はご利用ください。

そうでない場合は、かなり小さいlodash.invert npmパッケージの使用を検討する必要があります。

gulpを使用してテストする方法は次のとおりです。

1)次の内容でgulpfile.jsというファイルを作成します。

// Filename: gulpfile.js
var gulp = require('gulp');
var invert = require('lodash.invert');   
gulp.task('test-invert', function () {
  var hash = {
    foo: 1,
    bar: 2
  };
  var val = 1;
  var key = (invert(hash))[val];  // << Here's where we call invert!
  console.log('key for val(' + val + '):', key);
});

2)lodash.invertパッケージとgulpをインストールします

$ npm i --save lodash.invert && npm install gulp

3)機能することをテストします。

$ gulp test-invert
[17:17:23] Using gulpfile ~/dev/npm/lodash-invert/gulpfile.js
[17:17:23] Starting 'test-invert'...
key for val(1): foo
[17:17:23] Finished 'test-invert' after 511 μs

参考文献

https://www.npmjs.com/package/lodash.invert

https://lodash.com/

ロダッシュとアンダースコアの違い

https://github.com/gulpjs/gulp


ここでGulpが関与するのはなぜですか?スクリプトを実行するだけ
Ry-

0

アンダースコアjsソリューション

let samplLst = [{id:1,title:Lorem},{id:2,title:Ipsum}]
let sampleKey = _.findLastIndex(samplLst,{_id:2});
//result would be 1
console.log(samplLst[sampleKey])
//output - {id:2,title:Ipsum}

0

これは、オブジェクトのキー/値を取得するのに役立ちました。

let obj = {
        'key1': 'value1',
        'key2': 'value2',
        'key3': 'value3',
        'key4': 'value4'
    }
    Object.keys(obj).map(function(k){ 
    console.log("key with value: "+k +" = "+obj[k])    
    
    })
    


-1

本当に簡単です。

const CryptoEnum = Object.freeze({
                    "Bitcoin": 0, "Ethereum": 1, 
                    "Filecoin": 2, "Monero": 3, 
                    "EOS": 4, "Cardano": 5, 
                    "NEO": 6, "Dash": 7, 
                    "Zcash": 8, "Decred": 9 
                  });

Object.entries(CryptoEnum)[0][0]
// output => "Bitcoin"

6
オブジェクトの順序が同じである保証はありません...
Downgoat '11 / 07/18

-2

複雑にしないでおく!

洗練されたメソッドやライブラリでオブジェクトをフィルタリングする必要はありません。JavaScriptには、Object.valuesという組み込み関数があります。ます。

例:

let myObj = {jhon: {age: 20, job: 'Developer'}, marie: {age: 20, job: 
'Developer'}};

function giveMeTheObjectData(object, property) {
   return Object.values(object[property]);
}

giveMeTheObjectData(myObj, 'marie'); // => returns marie: {}

これにより、オブジェクトのプロパティデータが返されます。

参考文献

https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/values

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.