source

javascript 객체의 속성 서브셋을 가져오는 방법

manycodes 2022. 11. 25. 20:54
반응형

javascript 객체의 속성 서브셋을 가져오는 방법

대상이 있다고 가정해 보겠습니다.

elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
};

속성 중 일부를 사용하여 새 개체를 만들고 싶습니다.

 // pseudo code
 subset = elmo.slice('color', 'height')

 //=> { color: 'red', height: 'unknown' }

어떻게 하면 좋을까요?

오브젝트 파괴 및 속성 단축 사용

const object = { a: 5, b: 6, c: 7  };
const picked = (({ a, c }) => ({ a, c }))(object);

console.log(picked); // { a: 5, c: 7 }


Philipp Kewisch에서:

이것은 익명의 함수가 즉시 호출되는 것에 불과합니다.이 모든 내용은 MDN의 [Destructuring Assignment]페이지에서 확인할 수 있습니다.다음은 확장 폼입니다.

let unwrap = ({a, c}) => ({a, c});

let unwrap2 = function({a, c}) { return { a, c }; };

let picked = unwrap({ a: 5, b: 6, c: 7 });

let picked2 = unwrap2({a: 5, b: 6, c: 7})

console.log(picked)
console.log(picked2)

Lodash에 대해 살펴보는 것이 좋습니다. Lodash에는 많은 뛰어난 유틸리티 기능이 있습니다.

예를 들어 다음과 같은 것이 바로 당신이 원하는 것입니다.

var subset = _.pick(elmo, ['color', 'height']);

만지작거리다

두 가지 일반적인 접근 방식은 파괴적 접근 방식과 기존 Lodash 방식/omit실장 방식입니다.이들 간의 실질적인 주요 차이점은 파괴하려면 정적 키 목록이 필요하며, 이를 생략할 수 없으며, 존재하지 않는 선택된 키가 포함된다는 것입니다.이는 바람직한 경우와 그렇지 않은 경우가 있으며 구문을 파괴하기 위해 변경할 수 없습니다.

지정:

var obj = { 'foo-bar': 1, bar: 2, qux: 3 };

「 」의 .foo-bar,bar,baz 삭제:

{ 'foo-bar': 1, bar: 2 }

포괄적 선택 시 예상되는 결과:

{ 'foo-bar': 1, bar: 2, baz: undefined }

파괴하다

구문을 파괴하면 함수 파라미터 또는 변수를 사용하여 객체를 파괴하고 재결합할 수 있습니다.

키 정의되어 있기 때문에 할 수 입니다.가 아닌 경우( 영숫자.foo-bar.

장점은 ES6에 적합한 고성능 솔루션이라는 것입니다.

단점은 키 목록이 중복되므로 목록이 긴 경우 상세 코드가 생성됩니다.이 경우 파기 시 오브젝트 리터럴 구문이 중복되므로 목록을 그대로 복사하여 붙여넣을 수 있습니다.

라이프

const subset = (({ 'foo-bar': foo, bar, baz }) => ({ 'foo-bar': foo, bar, baz }))(obj);

임시 변수

const { 'foo-bar': foo, bar, baz } = obj;
const subset = { 'foo-bar': foo, bar, baz };

문자열 목록

선택한 키의 임의 목록은 질문에 따라 문자열로 구성됩니다.를 통해 키 이름인 키 할 수 .['foo-bar', someKey, ...moreKeys].

에는 ECMAScript 2017이 있습니다.★★Object.entries ★★★★★★★★★★★★★★★★★」Array.prototype.includes에는 , ECMAScript 2019가 있습니다.Object.fromEntries필요할 때 폴리필링할 수 있습니다.

한 줄

선택하는 객체에 추가 키가 포함되어 있는 것을 고려하면 일반적으로 객체 키보다 목록에서 키를 반복하는 것이 더 효율적이며 키를 생략해야 하는 경우에는 그 반대도 마찬가지입니다.

선택(ES5)

var subset = ['foo-bar', 'bar', 'baz']
.reduce(function (obj2, key) {
  if (key in obj) // line can be removed to make it inclusive
    obj2[key] = obj[key];
  return obj2;
}, {});

생략(ES5)

var subset = Object.keys(obj)
.filter(function (key) { 
  return ['baz', 'qux'].indexOf(key) < 0;
})
.reduce(function (obj2, key) {
  obj2[key] = obj[key];
  return obj2;
}, {});

선택(ES6)

const subset = ['foo-bar', 'bar', 'baz']
.filter(key => key in obj) // line can be removed to make it inclusive
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});

생략(ES6)

const subset = Object.keys(obj)
.filter(key => ['baz', 'qux'].indexOf(key) < 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});

선택(ES2019)

const subset = Object.fromEntries(
  ['foo-bar', 'bar', 'baz']
  .filter(key => key in obj) // line can be removed to make it inclusive
  .map(key => [key, obj[key]])
);

생략(ES2019)

const subset = Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => !['baz', 'qux'].includes(key))
);

재사용 가능한 기능

은 Lodash Lodash와 로 재사용 수 .pick ★★★★★★★★★★★★★★★★★」omit전달됩니다.pick(obj, 'foo-bar', 'bar', 'baz').

const pick = (obj, ...keys) => Object.fromEntries(
  keys
  .filter(key => key in obj)
  .map(key => [key, obj[key]])
);

const inclusivePick = (obj, ...keys) => Object.fromEntries(
  keys.map(key => [key, obj[key]])
);

const omit = (obj, ...keys) => Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => !keys.includes(key))
);

ES6를 사용하는 경우 파괴를 사용하여 이를 수행하는 매우 간결한 방법이 있습니다.파괴 기능을 사용하면 스프레드를 사용하여 개체에 쉽게 추가할 수 있지만 동일한 방식으로 하위 집합 개체를 만들 수도 있습니다.

const object = {
  a: 'a',
  b: 'b',
  c: 'c',
  d: 'd',
}

// Remove "c" and "d" fields from original object:
const {c, d, ...partialObject} = object;
const subset = {c, d};

console.log(partialObject) // => { a: 'a', b: 'b'}
console.log(subset) // => { c: 'c', d: 'd'};

좀 더 상세하게 설명하지만 Array.protype.reduce를 사용하면 2년 전에 다른 사람들이 추천했던 언더스코어/로드플래시를 실현할 수 있습니다.

var subset = ['color', 'height'].reduce(function(o, k) { o[k] = elmo[k]; return o; }, {});

이 접근방식은 오브젝트를 추출하여 속성 이름을 전달하는 대신 속성 이름 배열을 가져와 새 오브젝트로 축소하는 다른 측면에서 문제를 해결합니다.

가장 간단한 경우에서는 보다 상세하게 설명하지만, 여기서 콜백은 매우 편리합니다.예를 들어, 새로운 오브젝트의 「컬러」속성을 「컬러」로 변경해, 어레이를 평평하게 하는 등, 서비스/라이브러리로부터 오브젝트를 수신해, 다른 장소에 새로운 오브젝트를 작성할 때에 필요한 모든 작업을 간단하게 실시할 수 있기 때문입니다.언더스코어/로더시는 훌륭하고 구현이 잘 된 libs이지만, 벤더에 대한 의존도가 낮아지고 서브셋 구축 로직이 복잡해지면 보다 심플하고 일관성 있는 접근방식을 선호합니다.

편집: es7 버전 동일:

const subset = ['color', 'height'].reduce((a, e) => (a[e] = elmo[e], a), {});

편집: 카레링에도 좋은 예!'선택' 함수가 다른 함수를 반환하도록 합니다.

const pick = (...props) => o => props.reduce((a, e) => ({ ...a, [e]: o[e] }), {});

위의 방법은 '피커'를 즉석에서 구축할 수 있다는 점을 제외하고는 다른 방법과 매우 유사합니다.

pick('color', 'height')(elmo);

점은 어떤 할 수 입니다. '픽스'는 '픽스'를 '픽스'로 사용할 수 있습니다.Array#map:

[elmo, grover, bigBird].map(pick('color', 'height'));
// [
//   { color: 'red', height: 'short' },
//   { color: 'blue', height: 'medium' },
//   { color: 'yellow', height: 'tall' },
// ]

어떤 답변도 사용되지 않았기 때문에 이 답변을 추가합니다.

매우 간단합니다.,

const object = { a: 5, b: 6, c: 7  };
const picked = ({a,c} = object, {a,c})

console.log(picked);

코어 라이브러리에는 이러한 기능이 내장되어 있지 않지만 객체 파괴 기능을 사용하여 실행할 수 있습니다.

const {color, height} = sourceObject;
const newObject = {color, height};

효용 함수를 쓸 수도 있고...

const cloneAndPluck = function(sourceObject, keys) {
    const newObject = {};
    keys.forEach((obj, key) => { newObject[key] = sourceObject[key]; });
    return newObject;
};

const subset = cloneAndPluck(elmo, ["color", "height"]);

에도 Lodash가 ._.pick().

또 하나의 솔루션:

var subset = {
   color: elmo.color,
   height: elmo.height 
}

지금까지의 대답보다 훨씬 읽기 쉬워 보이지만, 어쩌면 저 혼자일지도 몰라요!

TypeScript 솔루션:

function pick<T extends object, U extends keyof T>(
  obj: T,
  paths: Array<U>
): Pick<T, U> {
  const ret = Object.create(null);
  for (const k of paths) {
    ret[k] = obj[k];
  }
  return ret;
}

입력 정보를 통해 자동 완성이 가능합니다.

확실한 신용장입력 대상U extends keyof T 트릭!

TypeScript 플레이그라운드

여기 아주 좋은 큐레이션이 있습니다.

pick-es2019.2012.pick

Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => ['whitelisted', 'keys'].includes(key))
);

pick-es2017.disc

Object.entries(obj)
.filter(([key]) => ['whitelisted', 'keys'].includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});

pick-es2015.pick

Object.keys(obj)
.filter((key) => ['whitelisted', 'keys'].indexOf(key) >= 0)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})

uscript-2019.199

Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => !['blacklisted', 'keys'].includes(key))
);

oscript-es2017.2017.2011.2015

Object.entries(obj)
.filter(([key]) => !['blacklisted', 'keys'].includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});

uscript-es2015.2015.2011

Object.keys(obj)
.filter((key) => ['blacklisted', 'keys'].indexOf(key) < 0)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})

Lodash를 이용하실 수도 있습니다.

var subset = _.pick(elmo ,'color', 'height');

보완적으로, "elmo" 배열이 있다고 가정해 보겠습니다.

elmos = [{ 
      color: 'red',
      annoying: true,
      height: 'unknown',
      meta: { one: '1', two: '2'}
    },{ 
      color: 'blue',
      annoying: true,
      height: 'known',
      meta: { one: '1', two: '2'}
    },{ 
      color: 'yellow',
      annoying: false,
      height: 'unknown',
      meta: { one: '1', two: '2'}
    }
];

Lodash를 사용하여 동일한 동작을 원하는 경우 다음과 같이 하십시오.

var subsets = _.map(elmos, function(elm) { return _.pick(elm, 'color', 'height'); });

질문에서 설명한 바와 같이 JavaScript에서는 동적으로 명명된 변수로의 파괴가 불가능합니다.

키를 동적으로 설정하려면 다음과 같이 객체를 변환하지 않고 축소 함수를 사용할 수 있습니다.

const getSubset = (obj, ...keys) => keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});

const elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
}

const subset = getSubset(elmo, 'color', 'annoying')
console.log(subset)

단, 단일 클론을 업데이트하는 대신 반복할 때마다 새 개체를 만듭니다.– mpen

아래는 단일 클론에서 reduce를 사용하는 버전입니다(초기값이 전달되어 감소).

const getSubset = (obj, ...keys) => keys.reduce((acc, curr) => {
  acc[curr] = obj[curr]
  return acc
}, {})

const elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
}

const subset = getSubset(elmo, 'annoying', 'height', 'meta')
console.log(subset)

동적 솔루션

['color', 'height'].reduce((a,b) => (a[b]=elmo[b],a), {})

let subset= (obj,keys)=> keys.reduce((a,b)=> (a[b]=obj[b],a),{});


// TEST

let elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
};

console.log( subset(elmo, ['color', 'height']) );

pick(이미). 라이브러리의 메서드.

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

_.pick(object, ['a', 'c']);

// => { 'a': 1, 'c': 3 }

https://lodash.com/docs/4.17.10#pick

불필요한 변수를 만들지 않는 가장 쉬운 방법은 호출할 수 있고 lodash와 동일하게 작동하는 함수입니다.

pick(obj, keys){
    return  Object.assign({}, ...keys.map(key => ({ [key]: obj[key] })))
}

예를 들어 다음과 같습니다.

pick(obj, keys){
    return  Object.assign({}, ...keys.map(key => ({ [key]: obj[key] })))
}
const obj = {a:1, b:2, c:3, d:4}
const keys = ['a', 'c', 'f']
const picked = pick(obj,keys)
console.log(picked)

pick = (obj, keys) => {
  return Object.assign({}, ...keys.map(key => ({
    [key]: obj[key]
  })))
}

const obj = {
  a: 1,
  b: 2,
  c: 3,
  d: 4
}
const keys = ['a', 'c', 'f']

const picked = pick(obj, keys)
console.log(picked)

오브젝트 배열

const aListOfObjects = [{
    prop1: 50,
    prop2: "Nothing",
    prop3: "hello",
    prop4: "What's up",
  },
  {
    prop1: 88,
    prop2: "Whatever",
    prop3: "world",
    prop4: "You get it",
  },
]

오브젝트의 서브셋을 작성하려면 오브젝트를 이 방법으로 파기해야 합니다.

const sections = aListOfObjects.map(({prop1, prop2}) => ({prop1, prop2}));

속기 객체 리터럴 구문과 함께 "with" 문 사용

아직 아무도 이 방법을 시연하지 않았는데, 아마 그건 끔찍하고 네가 하면 안 되기 때문일 거야. 하지만 나는 그것이 목록에 올라야 할 것 같아.

var o = {a:1,b:2,c:3,d:4,e:4,f:5}
with(o){
  var output =  {a,b,f}
}
console.log(output)

찬성: 속성 이름을 두 번 입력할 필요가 없습니다.

단점: "with" 문장은 여러 가지 이유로 권장되지 않습니다.

결론:효과는 좋지만, 사용하지 마세요.

다른 방법일 뿐인데...

var elmo = { 
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
}

var subset = [elmo].map(x => ({
  color: x.color,
  height: x.height
}))[0]

이 기능은 개체 배열 =과(와) 함께 사용할 수 있습니다.)

삭제할 속성보다 더 많은 속성을 유지할 경우 rest 파라미터 구문을 사용할 수 있습니다.

const obj = {
  a:1,
  b:2,
  c:3,
  d:4
};
const { a, ...newObj } = obj;
console.log(newObj); // {b: 2, c: 3, d: 4}

또 다른 난해한 방법을 추가할 수도 있습니다.

var obj = {a: 1, b:2, c:3}
var newobj = {a,c}=obj && {a,c}
// {a: 1, c:3}

소품 이름을 두 번 써야 돼요.

그럼 어떻게 해?

function sliceObj(obj) {
  var o = {}
    , keys = [].slice.call(arguments, 1);
  for (var i=0; i<keys.length; i++) {
    if (keys[i] in obj) o[keys[i]] = obj[keys[i]];
  }
  return o;
}

var subset = sliceObj(elmo, 'color', 'height');

Chrome 콘솔에서는 이 기능을 사용할 수 있습니다.무슨 문제라도 있나요?

var { color, height } = elmo
var subelmo = { color, height }
console.log(subelmo) // {color: "red", height: "unknown"}
  1. 인수를 배열로 변환하다

  2. 사용하다Array.forEach()물건을 고르다

    Object.prototype.pick = function(...args) {
       var obj = {};
       args.forEach(k => obj[k] = this[k])
       return obj
    }
    var a = {0:"a",1:"b",2:"c"}
    var b = a.pick('1','2')  //output will be {1: "b", 2: "c"}
    

이 스레드의 여러 가지와 마찬가지로, 나는 이것을 하는 가장 명백한 구식 방법이 실제로 사용 가능한 최선의 방법이라는 것에 동의한다.그러나 재미를 위해, 특정 상황에서 그것을 하는 다른 권장할 수 없는 방법을 제공하겠다.예를 들어, 서브셋이 이미 정의되어 있고, 슈퍼를 포함한 다른 오브젝트에서 서브셋에 속성을 복사하고 싶을 때속성 집합을 설정하거나 교차합니다.

let set = { a : 1, b : 2, c : 3 };
let subset = { a : null, b : null };
try {
  Object.assign(Object.seal(subset), set);
} catch (e) {
  console.log('its ok I meant to do that <(^.^)^');
}
console.log(subset);

굿 올드Array.prototype.reduce:

const selectable = {a: null, b: null};
const v = {a: true, b: 'yes', c: 4};

const r = Object.keys(selectable).reduce((a, b) => {
  return (a[b] = v[b]), a;
}, {});

console.log(r);

이 답변은 마법의 콤마 문자를 사용합니다.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

정말 화려해지고 싶다면 이게 더 콤팩트해요.

const r = Object.keys(selectable).reduce((a, b) => (a[b] = v[b], a), {});

이 모든 것을 재사용 가능한 기능으로 통합:

const getSelectable = function (selectable, original) {
  return Object.keys(selectable).reduce((a, b) => (a[b] = original[b], a), {})
};

const r = getSelectable(selectable, v);
console.log(r);

같은 문제를 안고, 다음의 립으로 간단하게 해결했습니다.

object.pick

https://www.npmjs.com/package/object.pick

pick({a: 'a', b: 'b', c: 'c'}, ['a', 'b'])
//=> {a: 'a', b: 'b'}

object.displaces

https://www.npmjs.com/package/object.omit

omit({a: 'a', b: 'b', c: 'c'}, ['a', 'c'])
//=> { b: 'b' }

이게 네 답이라고 생각해. (그리고 그걸 찾는 모든 사람들이)

const object = { a: 5, b: 6, c: 7  };
const subset = (({ a, c }) => ({ a, c }))(object);
console.log(subset); // { a: 5, c: 7 }
function splice()
{
    var ret = new Object();

    for(i = 1; i < arguments.length; i++)
        ret[arguments[i]] = arguments[0][arguments[i]];

    return ret;
}

var answer = splice(elmo, "color", "height");

동적 속성을 사용하여 할당 파기

이 솔루션은 특정 예에 적용할 뿐만 아니라 보다 일반적으로 적용할 수 있습니다.

const subset2 = (x, y) => ({[x]:a, [y]:b}) => ({[x]:a, [y]:b});

const subset3 = (x, y, z) => ({[x]:a, [y]:b, [z]:c}) => ({[x]:a, [y]:b, [z]:c});

// const subset4...etc.


const o = {a:1, b:2, c:3, d:4, e:5};


const pickBD = subset2("b", "d");
const pickACE = subset3("a", "c", "e");


console.log(
  pickBD(o), // {b:2, d:4}
  pickACE(o) // {a:1, c:3, e:5}
);

쉽게 정의할 수 있습니다.subset4더 많은 속성을 고려해야 합니다.

Ivan Nosov의 대답에 나의 2센트를 더하면:

내 경우 객체에서 '삭제'할 키가 많이 필요했기 때문에 객체는 매우 빠르게 볼썽사나워지고 동적 솔루션은 아닙니다.

const object = { a: 5, b: 6, c: 7, d: 8, aa: 5, bb: 6, cc: 7, dd: 8, aaa: 5, bbb: 6, ccc: 7, ddd: 8, ab: 5, bc: 6, cd: 7, de: 8  };
const picked = (({ a, aa, aaa, ab, c, cc, ccc, cd }) => ({ a, aa, aaa, ab, c, cc, ccc, cd }))(object);

console.log(picked);

eval을 사용하는 동적 솔루션은 다음과 같습니다.

const slice = (k, o) => eval(`(${k} => ${k})(o)`);


const object    = { a: 5, b: 6, c: 7, d: 8, aa: 5, bb: 6, cc: 7, dd: 8, aaa: 5, bbb: 6, ccc: 7, ddd: 8, ab: 5, bc: 6, cd: 7, de: 8  };
const sliceKeys = '({ a, aa, aaa, ab, c, cc, ccc, cd })';

console.log( slice(sliceKeys, object) );

언급URL : https://stackoverflow.com/questions/17781472/how-to-get-a-subset-of-a-javascript-objects-properties

반응형