값 JSON으로 키 교체


106

다음과 같이 구조화 된 매우 큰 JSON 개체가 있습니다.

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

객체의 키로 값을 바꿀 수있는 함수가 필요하지만 어떻게해야할지 모르겠습니다. 다음과 같은 출력이 필요합니다.

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

내가 이것을 할 수있는 방법이 있습니까? 모든 것이 스왑되는 새 개체를 수동으로 만들 수 있습니까?
감사


1
모든 값이 숫자이고 숫자가 반복됩니까? 값이 반복되면 값을 고유 한 값으로 변경하지 않는 한 다른 값을 덮어 쓰므로 바꿀 수 없습니다. 더 나은 해결책이있을 수 있습니다. 스왑이 필요한 이유는 무엇입니까?
Patrick Evans

@PatrickEvans 그들은 모두 숫자이지만 반복하지 않습니다. 기본 암호를 만들려고합니다.
C1D 2014

2
이와 같은 "스왑"작업은 [적어도] 두 가지 이유로 문제가된다는 점에 주목할 가치가 있습니다. 1) 값이 키가 될 때 문자열로 캐스트되므로 예기치 않은 "[object Object]"키가있을 때 놀라지 마십시오. 2) 중복 값 (문자열로 캐스트 한 후)을 덮어 씁니다. 적어도 # 1은 Object 대신 Map을 생성하여 해결할 수 있습니다.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
요즘 (2019)에 더 나은 해결책이 보입니다 ! 누군가 확인할 수 있겠죠? 성능이 좋습니까? 시맨틱은 완벽합니다. 이것이 정말 간단한 "맵 앤 스왑"솔루션이라는 것을 알 수 있습니다.
Peter Krauss

1
@ peter- krauss , 내가 뭔가를 놓친 경우 jsben.ch/gHEtn 을 사용하는 것을 환영 하지만이 답변과 jPO의 답변을 우연히 비교하면 jPO의 for-loop가 grappeq 의지도 접근 방식을 거의 3 대 1 (적어도 에 브라우저).
Michael Hays

36

객체의 키를 가져온 다음 Array의 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.keys감소 새로운와 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 }), {});

구문 오류 : /Users/markus/Entwicklung/IT1_Beleg/public/es6/vokabeltrainer.js : 예기치 않은 토큰 (53:45) 51 | if (btoa) {52 | 항목 = Object.entries (항목)> 53 | .reduce ((obj, [key, value]) => ({... obj, [value] : key}), {}); | ^
Superlokkus

@Superlokkus 오류 출력에 대한 가장 좋은 해석은 객체 확산 구문을 변환하지 않는다는 것입니다. 오늘 현재 기본적으로 지원하는 JavaScript 엔진을 모릅니다.
joslarson jul

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.


그래도 ... jPO의 답변은 거의 2 : 1만큼이 답변을 능가합니다. jsben.ch/R75aI (귀하의 의견이 오래 전의 것임을 알고 있지만 grappeq의 답변에 대해 의견을 말하고 있었고 귀하의 예제도 실행할 것이라고 생각했습니다).
Michael Hays

전체적으로 for 루프는 forEach, map또는 reduce메서드 보다 더 빠릅니다 . 나는 es6가 필요없는 한 줄짜리 솔루션을 갖기 위해이 응답을 만들었고 여전히 속도 / 효과 성 측면에서 관련성이 있습니다.
Vaidd4

2019 년 6 월이며 최신 Google 크롬에서는 더 이상 사실이 아닙니다. 이제 그 차이는 거의 존재하지 않습니다 (9:10)
Ivan Castellanos 19

이것은 ES6 변종 중 가장 성능이 뛰어난 것으로 보입니다 : jsben.ch/HvICq
Brian M. Hunt


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가 제안하는 한 줄 솔루션이나 간단한 for 루프보다 또 다른 라이브러리를 사용하는 것이 더 나은 이유는 무엇입니까?
Arel

1

순수하고 포인트없는 스타일의 순수 Ramda 사용 :

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 어디에서 왔습니까?
막심 LAUNOIS

그리고 이것은 무엇이 아닙니다 map , 당신이 좋아 여기를 사용 할 예정이다forEach
barbsan

나는 forEach를 사용한 적이 없습니다. underscore.js의 각 함수를 사용하므로 forEach에 대해 몰랐습니다. @barbsan 주셔서 감사합니다
아누 프 아가 왈

0

다음은 뒤집기 keysvaluesES6 의 순수한 기능적 구현입니다 .

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 {};
    }
  }

자바 스크립트

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.