[javascript] JavaScript : 객체 용 filter ()

ECMAScript 5에는 유형에 대한 filter()프로토 타입이 Array있지만 Object올바르게 이해하면 유형이 아닙니다 .

JavaScript에서 filter()for를 어떻게 구현 Object합니까?

이 객체가 있다고 가정 해 봅시다.

var foo = {
    bar: "Yes"
};

그리고 s에서 filter()작동 하는을 작성하고 싶습니다 Object.

Object.prototype.filter = function(predicate) {
    var result = {};

    for (key in this) {
        if (this.hasOwnProperty(key) && !predicate(this[key])) {
            result[key] = this[key];
        }
    }

    return result;
};

이것은 다음 데모에서 사용할 때 작동하지만 jQuery 1.5 및 jQuery UI 1.8.9를 사용하는 사이트에 추가하면 FireBug에서 JavaScript 오류가 발생합니다.



답변

절대 확장하지 마십시오 Object.prototype.

코드에 끔찍한 일이 생길 것입니다. 상황이 깨질 것입니다. 객체 리터럴을 포함하여 모든 객체 유형을 확장 하고 있습니다.

시도해 볼 수있는 간단한 예는 다음과 같습니다.

    // Extend Object.prototype
Object.prototype.extended = "I'm everywhere!";

    // See the result
alert( {}.extended );          // "I'm everywhere!"
alert( [].extended );          // "I'm everywhere!"
alert( new Date().extended );  // "I'm everywhere!"
alert( 3..extended );          // "I'm everywhere!"
alert( true.extended );        // "I'm everywhere!"
alert( "here?".extended );     // "I'm everywhere!"

대신 객체를 전달하는 함수를 작성하십시오.

Object.filter = function( obj, predicate) {
    let result = {}, key;

    for (key in obj) {
        if (obj.hasOwnProperty(key) && !predicate(obj[key])) {
            result[key] = obj[key];
        }
    }

    return result;
};


답변

우선, 확장하는 것은 나쁜 습관으로 간주됩니다Object.prototype . 대신에 유틸리티 함수로 기능을 제공하는 Object이미있다처럼 Object.keys, Object.assign, Object.is, … 등.

여기에 몇 가지 솔루션을 제공합니다.

  1. 사용 reduce하여Object.keys
  2. (1)과 같이 Object.assign
  3. map대신 구문 사용 및 확산reduce
  4. 사용 Object.entries하여Object.fromEntries

1. 사용 reduceObject.keys

reduce하고 Object.keys원하는 필터 (ES6하여 구현하는 화살표 구문 )

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

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1);
console.log(filtered);

위 코드 에서 OP가 사용한 제외 조건 과 달리 포함 조건 이 작동 방식 과 일치하도록 포함 조건 predicate이어야 합니다.Array.prototype.filter

2. (1)과 같이 Object.assign

위의 솔루션에서 쉼표 연산자reduce부분에서 돌연변이 된 res객체 를 반환하는 데 사용됩니다 . 이것은 물론 하나의 표현 대신 두 개의 진술로 쓰여질 수 있지만 후자는 더 간결합니다. 쉼표 연산자없이 작업을 수행하려면, 당신은 사용할 수 Object.assign있는 대신 않는 돌연변이 개체를 반환 :

Object.filter = (obj, predicate) =>
    Object.keys(obj)
          .filter( key => predicate(obj[key]) )
          .reduce( (res, key) => Object.assign(res, { [key]: obj[key] }), {} );

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1);
console.log(filtered);

3. map대신 구문 사용reduce

여기서 우리 Object.assign는 루프 밖으로 호출 을 이동 하므로 한 번만 만들어 개별 키를 별도의 인수로 ( spread 구문 사용 ) 전달합니다.

Object.filter = (obj, predicate) =>
    Object.assign(...Object.keys(obj)
                    .filter( key => predicate(obj[key]) )
                    .map( key => ({ [key]: obj[key] }) ) );

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1);
console.log(filtered);

4. 사용 Object.entriesObject.fromEntries

용액은 중간 어레이 객체를 변환 한 후, 일반 오브젝트에 그 위로 변환, 사용하기 위해 유용 할 것이다 Object.entries(즉, (ES2017)과 반대 키 / 값 쌍의 어레이로부터 객체를 생성 하여) Object.fromEntries( ES2019).

이 “한 줄짜리”방법으로 이어집니다 Object.

Object.filter = (obj, predicate) =>
                  Object.fromEntries(Object.entries(obj).filter(predicate));

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};

var filtered = Object.filter(scores, ([name, score]) => score > 1);
console.log(filtered);

술어 함수는 여기에서 인수로 키 / 값 쌍을 가져옵니다. 이는 약간 다르지만 술어 함수의 논리에서 더 많은 가능성을 허용합니다.


답변

밑줄 또는 lodash 를 사용하려는 경우 pick(또는 그 반대 omit)를 사용할 수 있습니다 .

밑줄 문서의 예 :

_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
// {name: 'moe', age: 50}

또는 콜백 ( lodash 의 경우 pickBy 사용 )을 사용 하십시오 .

_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
  return _.isNumber(value);
});
// {age: 50}


답변

ES6 접근법 …

아래에이 객체가 있다고 상상해보십시오.

const developers = {
  1: {
   id: 1,
   name: "Brendan",
   family: "Eich"
  },
  2: {
   id: 2,
   name: "John",
   family: "Resig"
  },
  3: {
   id: 3,
   name: "Alireza",
   family: "Dezfoolian"
 }
};

함수를 작성하십시오.

const filterObject = (obj, filter, filterValue) =>
   Object.keys(obj).reduce((acc, val) =>
   (obj[val][filter] === filterValue ? acc : {
       ...acc,
       [val]: obj[val]
   }
), {});

그리고 그것을 부르십시오 :

filterObject(developers, "name", "Alireza");

그리고 반환합니다 :

{
  1: {
  id: 1,
  name: "Brendan",
  family: "Eich"
  },
  2: {
   id: 2,
   name: "John",
   family: "Resig"
  }
}


답변

패트릭은 이미 언급했듯이 사용하기를 원하는 타사 코드를 거의 확실하게 깨뜨릴 수 있으므로 나쁜 생각입니다.

확장하면 jquery 또는 prototype과 같은 모든 라이브러리가 중단됩니다. 추가하는 함수가 반복의 일부이기 때문에 검사 Object.prototype하지 않고 객체에 대한 지연 반복 hasOwnProperty이 중단되기 때문입니다.


답변

어때요?

function filterObj(keys, obj) {
  const newObj = {};
  for (let key in obj) {
    if (keys.includes(key)) {
      newObj[key] = obj[key];
    }
  }
  return newObj;
}

또는…

function filterObj(keys, obj) {
  const newObj = {};
  Object.keys(obj).forEach(key => {
    if (keys.includes(key)) {
      newObj[key] = obj[key];
    }
  });
  return newObj;
}


답변

주어진

object = {firstname: 'abd', lastname:'tm', age:16, school:'insat'};

keys = ['firstname', 'age'];

그때 :

keys.reduce((result, key) => ({ ...result, [key]: object[key] }), {});
// {firstname:'abd', age: 16}