Underscore.js를 사용하여 개체에서 빈 속성 / 잘못된 값 제거


83

여러 속성을 가진 개체가 있습니다. 잘못된 값이있는 속성을 제거하고 싶습니다.

이것은 compact배열에서 얻을 수 있지만 객체는 어떻습니까?


저장소간에 복사 붙여 넣기를 방지하려면 Bit 를 사용 하여이 구성 요소가져올 수 있습니다 (3 개의 테스트 통과 및 MIT 라이선스 포함). 이 NPM 패키지를 사용해 볼 수도 있습니다 (작은 구성 요소의 경우 과잉 일 수 있음).
Yoni

답변:


47

자신 만의 밑줄 플러그인 (mixin)을 만들 수 있습니다.

_.mixin({
  compactObject: function(o) {
    _.each(o, function(v, k) {
      if(!v) {
        delete o[k];
      }
    });
    return o;
  }
});

그런 다음 기본 밑줄 방법으로 사용하십시오.

var o = _.compactObject({
  foo: 'bar',
  a: 0,
  b: false,
  c: '',
  d: null,
  e: undefined
});

최신 정보

같이 @AndreiNeculau는 지적 원래하지만,이 믹스 인은, 원래 객체에 영향을 미치는 compact밑줄 방법은 배열의 카피를 돌려줍니다 .
이 문제를 해결하고 사촌compactObject 처럼 행동하도록 하기 위해 다음과 같은 사소한 업데이트가 있습니다.

_.mixin({
  compactObject : function(o) {
     var clone = _.clone(o);
     _.each(clone, function(v, k) {
       if(!v) {
         delete clone[k];
       }
     });
     return clone;
  }
});

1
질문에 밑줄 참조가 있기 때문에 이처럼 작동하지 않는다는 점을 언급하는 것이 좋습니다 _.compact. 진실 값만있는 얕은 복제본을 생성하는 대신 속성을 삭제합니다. 아래 stackoverflow.com/a/19750822/465684 참조
Andrei Neculau 2014 년

@AndreiNeculau 맞아요! 나는 일찍 그것을 놓친 것 같습니다. 업데이트 된 답변을 참조하십시오.
gion_13 2014 년

3
먼저 객체의 모든 속성을 복사 한 다음 반복해서 잘못된 속성을 삭제하는 이유는 무엇입니까? 성능이 좋지 않습니다. 더욱이 사용 delete은 일반적으로 프로토 타입 체인에서 동일한 이름의 속성을 즉시 노출하고 "숨겨진 클래스"(V8)로 인해 성능이 저하되므로 일반적으로 사용하지 않는 것이 좋습니다. 개체 구조를 변경하면 엔진이 추가 작업을 수행하게됩니다. 가장 좋고 가장 짧은 해결책은 _.pick(o, _.identity).
Radko Dinev 2014 년

170

Underscore 버전 1.7.0부터 다음을 사용할 수 있습니다 _.pick.

_.pick(sourceObj, _.identity)

설명

두 번째 매개 변수 _.pick는 값 선택을위한 술어 함수가 될 수 있습니다. 술어가 진실 을 리턴하는 값 이 선택되고 술어가 거짓 을 리턴하는 값 은 무시됩니다.

선택 _.pick (객체, * 키)

화이트리스트에있는 (또는 유효한 키의 배열)에 대한 값만 갖도록 필터링 된 객체 의 복사본을 반환합니다 . 또는 선택할 키를 나타내는 술어를 승인합니다.

_.identity첫 번째 인수를 반환하는 도우미 함수입니다. 즉, 진실 값을 선택하고 거짓 값을 거부하는 조건 자 함수로도 작동합니다. Underscore 라이브러리는 예를 들어 다른 술어와 함께 제공됩니다._.pick(sourceObj, _.isBoolean) 부울 속성 만 유지합니다.

이 기술을 많이 사용하는 경우 좀 더 표현력이있게 만들 수 있습니다.

var pickNonfalsy = _.partial(_.pick, _, _.identity); // Place this in a library module or something
pickNonfalsy(sourceObj);

밑줄 버전 1.6.0도 제공 _.pick되었지만 화이트리스트 대신 조건 자 함수를 허용하지 않았습니다.


2
_.identity기능 을 언급 해 주셔서 감사 합니다. 매우 편리합니다.
ivkremer

9
이것은 매우 편리했습니다! _.omit(sourceObj, _.isUndefined)정의되지 않은 값 (false, null, 0 허용) 만 제거하는 데 사용할 수도 있습니다 .
벤 패터슨

1
그것 또한 가능하여 수행하는 pick(obj, Boolean)경우 같은 방법이 사용될 수 있다는 것을 falsey 값을 제거하기 위해 arr.filter(Boolean)... falsey 값의 배열을 청소
데이비드 체이스

3
ES6에서는 다음과 같이 바뀝니다._.pick(sourceObj, prop => prop)
Deniz Ozger 2015-08-27

16
lodash 4.4.0에서는 _.pick사후 사용에서 언급 _.pickBy
한대로이

45

퀵앤 클리어 : _.omitBy( source, i => !i );

이것은 Emil의 대답에 역으로 언급됩니다. 이런 식으로 imho는 더 명확하게 읽습니다. 더 자명합니다.

ES6의 고급 스러움이 없다면 약간 덜 깨끗합니다. _.omitBy( source, function(i){return !i;});

번갈아 하는: _.omitBy( source, _.isEmpty)

진실성 _.isEmpty대신을 사용 하면 컬렉션에서 빈 배열과 객체를 편리하게 제거 할 수 있으며 아마도 숫자와 날짜를 불편하게 제거 할 수 있습니다 . 따라서 결과는 OP의 질문에 대한 정확한 대답은 아니지만 빈 컬렉션을 제거하려는 경우 유용 할 수 있습니다._.identity


8
Lodash 4.0에서이 기능은 현재 omitBy. lodash.com/docs#omitBy
JackMorrissey

3
:이 같은이라고 생각 _.pick(source, i => i); 하는가 부정 방지
제프 로워

2
@JeffLowery Lodash에서는 기본 술어가 identity 함수이기 때문에 더 좋습니다! _.pickBy(source)필요한 모든 것입니다.
Shibumi

참고 : 숫자는 비어있는 것으로 간주됩니다. _.isEmpty(5) === true. 따라서 숫자 인 값은 삭제됩니다.
Sir.Nathan Stassen

21

lodash의 변형 으로

_.transform(obj, function(res, v, k) {
  if (v) res[k] = v;
});

23
whit lodash의 _.pick (obj, _.identity); 더 짧아 진 ^ _ ^
evilive 2014 년

이 대답 또는 그 아래의 @evilive의 의견이 대답입니다.
Radko Dinev 2014 년

2
위의 의견에 따라 짧은 변이는 것var compactObject = _.partialRight(_.pick, _.identity);
zaboco


yse, _.pickBy(object)모두 당신이 필요
wdetac


9

얕은 클론을 생성 할 수 있습니다.

_(obj).reduce(function(a,v,k){ 
     if(v){ a[k]=v; } 
     return a; 
},{});

5

개체 사용 삭제.

for(var k in obj){

  if(obj.hasOwnProperty(k) && !obj[k]){
    delete obj[k];
  }
}

그는 밑줄 솔루션을 원하기 때문에, 당신은 밑줄의 방법 중 하나를 사용하여 배열을 반복 할 수
gion_13을

5

갑자기 나는 재귀 적으로 허위를 제거하는 함수를 만들어야했습니다. 이게 도움이 되길 바란다. 저는 Lodash를 사용하고 있습니다.

var removeFalsies = function (obj) {
    return _.transform(obj, function (o, v, k) {
        if (v && typeof v === 'object') {
            o[k] = _.removeFalsies(v);
        } else if (v) {
            o[k] = v;
        }
    });
};

_.mixin({ 'removeFalsies': removeFalsies });

그런 다음 사용할 수 있습니다.

var o = _.removeFalsies({
  foo: 'bar',
  a: 0,
  b: false,
  c: '',
  d: null,
  e: undefined,
  obj: {
    foo: 'bar',
    a: 0,
    b: false,
    c: '',
    d: null,
    e: undefined
  }
});

// {
//   foo: 'bar',
//   obj: {
//     foo: 'bar'
//   }
// }

1

gion_13의 답변에 추가하려면 :

_.mixin({
  compactObject : function(o) {
     var newObject = {};
     _.each(o, function(v, k) {
       if(v !== null && v !== undefined) {
         newObject[k] = v
       }
     });
     return newObject;
  }
});

이것은 새로운 객체를 만들고 모든 것을 복제하고 키-값 쌍을 삭제하는 대신 키와 값을 추가합니다. 사소한 차이.

그러나 더 중요한 것은 false 대신 null 및 undefined를 명시 적으로 확인하여 값이 false 인 키-값 쌍을 삭제합니다.



-1

_.compact배열에 사용하기 위해 문서화되어 있지만 . 객체에도 작동하는 것 같습니다. 크롬, 오페라 및 파이어 폭스 콘솔에서 다음을 실행했습니다.

var obj = {first: 1, second: null, third: 3, fourth: function(){return 5}}
undefined
_.compact(obj)

[1, 3, function()]

업데이트 : 샘플 _.compact에서 객체를 호출 하면 키가 삭제되고 압축 된 배열이 반환 됨이 나타납니다 .


1
그러나 여전히 배열을 반환합니다. 열쇠가 분실되었습니다.
Turadg

1
네가 옳아. 그러면 내 답변을 삭제합니까? 아니면 stackoverflow가 다른 것을 선호합니까?
tzvi

2
커뮤니티 선호도는 모르지만, 탈퇴해도 괜찮다면 다른 사람이 비슷한 답변을 추가하지 못하도록 막을 가치가있을 수 있습니다.
Turadg
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.