キーと値JSONを交換する


106

次のような構造の非常に大きなJSONオブジェクトがあります。

{A : 1, B : 2, C : 3, D : 4}

オブジェクトのキーと値を交換できる関数が必要ですが、その方法がわかりません。私はこのような出力が必要でしょう:

{1 : A, 2 : B, 3 : C, 4 : D}

すべてを交換する新しいオブジェクトを手動で作成する方法はありますか?
ありがとう


1
すべての値は数値であり、数値は繰り返されますか?値が繰り返される場合、値をいくつかの一意の値に変更しない限り、値が他のものを上書きするため、それらを交換することはできません。スワップが必要な理由は何ですか?
Patrick Evans 14

@PatrickEvansそれらはすべて数字ですが、繰り返されません。基本的な暗号を作ろうとしています。
C1D 2014

2
このような「スワップ」操作は、[少なくとも] 2つの理由で問題があることに注意してください。1)値がキーになるときに文字列にキャストされるため、予期しない「[オブジェクトオブジェクト]」キーがある場合でも驚かないでください。2)重複する値(文字列にキャストした後)は上書きされます。#1、少なくとも、thusly、代わりにオブジェクトのマップを生成することによって解決することができる:function swap(obj) {return new Map(Object.entries(x).map([k, v] => [v, k]))}
broofa

回答:


118
function swap(json){
  var ret = {};
  for(var key in json){
    ret[json[key]] = key;
  }
  return ret;
}

ここの例FIDDLEは、結果を表示するためにコンソールをオンにすることを忘れないでください。


ES6バージョン:

static objectFlip(obj) {
  const ret = {};
  Object.keys(obj).forEach(key => {
    ret[obj[key]] = key;
  });
  return ret;
}

または、Array.reduce()Object.keys()を使用する

static objectFlip(obj) {
  return Object.keys(obj).reduce((ret, key) => {
    ret[obj[key]] = key;
    return ret;
  }, {});
}

または、Array.reduce()Object.entries()を使用する

static objectFlip(obj) {
  return Object.entries(obj).reduce((ret, entry) => {
    const [ key, value ] = entry;
    ret[ value ] = key;
    return ret;
  }, {});
}

44

あなたが使用することができます_.invert lodash機能を、それはまたmultivlaueを使用することができます

 var object = { 'a': 1, 'b': 2, 'c': 1 };

  _.invert(object);
  // => { '1': 'c', '2': 'b' }

  // with `multiValue`
  _.invert(object, true);
  // => { '1': ['a', 'c'], '2': ['b'] }

39

ES6の使用:

const obj = { a: "aaa", b: "bbb", c: "ccc", d: "ddd" };
Object.assign({}, ...Object.entries(obj).map(([a,b]) => ({ [b]: a })))

2
そうです、よりよい解決策 nowdays(2019)のためには!誰か確認できますか?パフォーマンスは良いですか?セマンティックは完璧です。これは本当に単純な「マップアンドスワップ」ソリューションであることがわかります。
Peter Krauss、

1
@ peter-krauss、私が何かを見逃した場合に備えてjsben.ch/gHEtnをいじるのは大歓迎ですが、この回答とjPOの回答をさりげなく比較すると、jPOのforループがgrappeqのマップアプローチをほぼ3対1で上回っています(少なくとも上の私のブラウザ)。
マイケルヘイズ

36

オブジェクトのキーを取得し、配列のreduce関数を使用して各キーを調べ、値をキーとして、キーを値として設定します。

const data = {
  A: 1,
  B: 2,
  C: 3,
  D: 4
}
const newData = Object.keys(data).reduce(function(obj, key) {
  obj[data[key]] = key;
  return obj;
}, {});
console.log(newData);


30

ES6 / ES2015では、Object.keysreduceの使用を新しいObject.assign関数、矢印関数計算されたプロパティ名と組み合わせて、非常に簡単な単一ステートメントソリューションを実現できます。

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.keys(foo)
    .reduce((obj, key) => Object.assign({}, obj, { [foo[key]]: key }), {});

オブジェクトスプレッドオペレーター(これを書いている時点ではステージ3)を使用してトランスパイルしている場合は、少し簡単になります。

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.keys(foo)
    .reduce((obj, key) => ({ ...obj, [foo[key]]: key }), {});

最後に、Object.entriesを使用できる場合(執筆時点ではステージ4)、ロジックをもう少しクリーンアップできます(IMO)。

const foo = { a: 1, b: 2, c: 3 };
const bar = Object.entries(foo)
    .reduce((obj, [key, value]) => ({ ...obj, [value]: key }), {});

SyntaxError:/Users/markus/Entwicklung/IT1_Beleg/public/es6/vokabeltrainer.js:予期しないトークン(53:45)51 | if(btoa){52 | entries = Object.entries(entries)> 53 | .reduce((obj、[key、value])=>({... obj、[value]:key})、{}); | ^
Superlokkus 2017年

@Superlokkusそのエラー出力の私の最良の解釈は、オブジェクトスプレッド構文をトランスパイルしていないということです。現在のところ、それをネイティブにサポートするJavaScriptエンジンは知りません。
joslarson 2017

1
@grappeqのソリューションを参照してください、より良いようです(最も簡単です!)。
Peter Krauss、

16

これでObject.fromEntriesができました。

obj => Object.fromEntries(Object.entries(obj).map(a => a.reverse()))

または

obj => Object.fromEntries(Object.entries(obj).map(([k, v]) => ([v, k])))

Node.jsバージョン12以降のオブジェクトスワップの標準的な方法である必要があります。
破損したオーガニック

4

@joslarsonと@jPOの回答を補完するものとして、
ES6が不要な場合は、カンマ演算子とを使用できます。Object.keys Array.reduce

Object.keys(foo).reduce((obj, key) => (obj[foo[key]] = key, obj), {});

見苦しい人もいるかもしれreduceませんがobj、各ループのonのすべてのプロパティが拡散されないため、「少し」速くなります。


それでも... jPOの回答はこれをほぼ2:1で上回っています。jsben.ch/R75aI (あなたのコメントはずっと前からだったと思いますが、grappeqの回答についてコメントしていて、私もあなたの例を実行すると思いました)。
マイケルヘイズ

完全に、forループはforEachmapまたはreduceメソッドよりも高速です。私は、es6を必要とせずにワンライナーソリューションを持ち、スピード/有効性の点で依然として関連があるように、この応答を行いました。
Vaidd4

2019年6月であり、最新のGoogle Chromeには当てはまらない、違いはほとんど存在しない(9:10)
Ivan Castellanos

これは、ES6バリアントの中で最もパフォーマンスが高いようです:jsben.ch/HvICq
ブライアンM.ハント


2

ES6を使用して思いついた最も短いもの。

const original = {
 first: 1,
 second: 2,
 third: 3,
 fourth: 4,
};


const modified = Object
  .entries(original)
  .reduce((all, [key, value]) => ({ ...all, [value]: key }), {});

console.log('modified result:', modified);


1

Ramdaの使用:

const swapKeysWithValues = 
  R.pipe(
    R.keys,
    R.reduce((obj, k) => R.assoc(source[k], k, obj), {})
  );

const result = swapKeysWithValues(source);

1

このようなnpmモジュールを使用してこのタスクを実行する方が良いと思いますinvert-kv

invert-kv:オブジェクトのキー/値を反転します。例:{foo: 'bar'}→{bar: 'foo'}

https://www.npmjs.com/package/invert-kv

const invertKv = require('invert-kv');

invertKv({foo: 'bar', unicorn: 'rainbow'});
//=> {bar: 'foo', rainbow: 'unicorn'}

1
@ Sc0ttyDが提案するような1行のソリューション、または単純なforループよりもさらに別のライブラリを使用するのはなぜですか?
Arel、

1

純粋でポイントフリーなスタイルの純粋なラムダで:

const swapKeysAndValues = R.pipe(
   R.toPairs,
   R.map(R.reverse),
   R.fromPairs,
);

または、少し複雑なES6バージョンでも、純粋に機能します。

const swapKeysAndValues2 = obj => Object
    .entries(obj)
    .reduce((newObj, [key, value]) => ({...newObj, [value]: key}), {})

0
    var data = {A : 1, B : 2, C : 3, D : 4}
    var newData = {};
    Object.keys(data).forEach(function(key){newData[data[key]]=key});
    console.log(newData);

3
これはobjectどこから来たのですか?
Maxime Launois

これはmap本来の目的ではなく、ここで使用していますforEach
barbsan

forEachを使用したことはありません。私はunderscore.jsの各関数を使用しているため、forEachについては知りませんでした。ありがとう@barbsan
Anup Agarwal

0

これはフリッピングの純粋な機能実装でkeysあり、values ES6では:

TypeScript

  const flipKeyValues = (originalObj: {[key: string]: string}): {[key: string]: string} => {
    if(typeof originalObj === "object" && originalObj !== null ) {
      return Object
      .entries(originalObj)
      .reduce((
        acc: {[key: string]: string}, 
        [key, value]: [string, string],
      ) => {
        acc[value] = key
        return acc;
      }, {})
    } else {
      return {};
    }
  }

JavaScript

const flipKeyValues = (originalObj) => {
    if(typeof originalObj === "object" && originalObj !== null ) {
        return Object
        .entries(originalObj)
        .reduce((acc, [key, value]) => {
          acc[value] = key
          return acc;
        }, {})
    } else {
        return {};
    }
}

const obj = {foo: 'bar'}
console.log("ORIGINAL: ", obj)
console.log("FLIPPED: ", flipKeyValues(obj))


0
function swapKV(obj) {
  const entrySet = Object.entries(obj);
  const reversed = entrySet.map(([k, v])=>[v, k]);
  const result = Object.fromEntries(reversed);
  return result;
}

これは、オブジェクトを{A : 1, B : 2, C : 3, D : 4}配列のようにすることができるので、

const o = {A : 1, B : 2, C : 3, D : 4}
const arrayLike = swapKV(o);
arrayLike.length = 5;
const array = Array.from(arrayLike);
array.shift(); // undefined
array; // ["A", "B", "C", "D"]

0

オブジェクトが{a:1、b:2、c:2}の場合、値とキーを交換しますが重複を失わないオプションは次のとおりです。常に出力に配列を返します。

function swapMap(map) {
    const invertedMap = {};
    for (const key in map) {
        const value = map[key];
        invertedMap[value] = invertedMap[value] || [];
        invertedMap[value].push(key);
    }
    return invertedMap;
}
swapMap({a: "1", b: "2", c: "2"})
// Returns => {"1": ["a"], "2":["b", "c"]}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.