জাভাস্ক্রিপ্ট: অবজেক্টের জন্য ফিল্টার ()


185

ECMAScript 5 তে প্রকারের filter()জন্য প্রোটোটাইপ রয়েছে Array, তবে Objectপ্রকার নয় , যদি আমি সঠিকভাবে বুঝতে পারি।

আমি কীভাবে জাভাস্ক্রিপ্টে একটি এর filter()জন্য বাস্তবায়ন করব Object?

ধরা যাক আমার এই জিনিসটি রয়েছে:

var foo = {
    bar: "Yes"
};

এবং আমি একটি লিখতে চাই 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 ব্যবহার করে, আমি ফায়ারব্যাগে জাভাস্ক্রিপ্ট ত্রুটি পাই।


আপনি বিশেষত কোন ত্রুটিগুলি পান?
এনটি

আপনি কী ত্রুটিগুলি পাচ্ছেন? সম্ভব হলে এগুলি পোস্ট করুন :)
হিউম্যান জ্যাক করুন

অস্পষ্ট ইতিহাসের কিছুটা ঝুঁকিপূর্ণ jQuery এবং স্ক্রিপ্ট রয়েছে যা প্রসারিত হয়েছে Object.prototype: বাগস.জকোয়ারি
ক্রিসেন্ট ফ্রেশ

ঠিক আমার যা প্রয়োজন, তা বাদ দিয়ে আপনি অবশ্যই ""! প্রকৃত ফিল্টার পদ্ধতি আছে! প্রিিকেট (এটি [কী]) এ।
নক্সফ্লাই

উত্তর:


200

কখনও প্রসারিত না 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;
};

60
@ পেট্রিক: একজনকে একটি রুটি দিন এবং আপনি তাকে একদিনের জন্য খাওয়ান, কীভাবে বেক করবেন তা শিখিয়ে দিন এবং আপনি তাকে আজীবন খাওয়াবেন (বা কিছু, আমি ডেনিশ, আমি সঠিক ইংরেজি উক্তিটি জানি না ;)
মার্টিন জেসপারসেন

13
আপনি এটি ভুল করছেন ...! প্রিডিটেক্ট (আপত্তি [কী]) হ'ল প্রাকটিক (আবজ [কী]) হওয়া উচিত
পাইরোটেকনিক

6
@ এপ্রোটেকনিক: না No. প্রথম, উত্তরের মূল বিষয়টি প্রসারিত না করা Object.prototype, বরং কেবল ফাংশনটি চালিয়ে যাওয়া Object। দ্বিতীয়ত, এটি অপের কোড । স্পষ্টত ওপি এর উদ্দেশ্য আছে হয় .filter()এমন হতে এটা যে আউট ফিল্টার ইতিবাচক ফলাফল নেই। অন্য কথায়, এটি একটি নেতিবাচক ফিল্টার, যেখানে ইতিবাচক প্রত্যাবর্তনের মান মানে এটি ফলাফল থেকে বাদ থাকে । আপনি যদি jsFizz উদাহরণটি দেখুন, তিনি বিদ্যমান বৈশিষ্ট্যগুলি ফিল্টার করছেন undefined
ব্যবহারকারী 113716

4
@ পেট্রিক ডাব্লু: না, প্রথম, আমি প্রোটোটাইপগুলি বাড়ানো / না বাড়ানোর কথা উল্লেখ করি নি। দ্বিতীয়ত, বিকাশকারী.মোজিলা.অর্গ / জেনা জাভাস্ক্রিপ্ট / রেফারেন্স / গ্লোবাল_অবজেক্টস_… - "প্রদত্ত ফাংশন দ্বারা প্রয়োগিত পরীক্ষায় পাস হওয়া সমস্ত উপাদানগুলির সাথে একটি নতুন অ্যারে তৈরি করে।" বিশ্বব্যাপী ঠিক এর বিপরীতটি প্রয়োগ করা বেশ নির্বোধ বলে মনে হয়, তাই না?
পাইরোটেকনিক

7
@ এপ্রোটেকনিক: এটি ঠিক, আপনি প্রোটোটাইপগুলি বাড়ানো / না বাড়ানোর কথা উল্লেখ করেননি এবং এটিই আমার বক্তব্য। আপনি বলেছিলেন আমি এটি ভুল করছি, তবে কেবলমাত্র "এটি" হ'ল ওপিকে না বাড়াতে বলছে Object.prototype। প্রশ্ন থেকে: "এটি কাজ করে ... তবে যখন আমি এটি আমার সাইটে যুক্ত করি ... তখন আমি জাভাস্ক্রিপ্ট ত্রুটি পেয়েছি" ওপি যদি .filter()এর বিপরীত আচরণের সাথে একটি বাস্তবায়ন করার সিদ্ধান্ত নেয় Array.prototpe.filter, এটি তার / তার উপর নির্ভর করে । আপনি যদি কোডটি ভুল বলে ওপিকে অবহিত করতে চান তবে দয়া করে প্রশ্নের অধীনে একটি মন্তব্য করুন তবে আমাকে বলবেন না যে এটি আমার কোড না হলে আমি এটি ভুল করছি
ব্যবহারকারী 113716

278

প্রথমত, এটি প্রসারিত করা খারাপ অভ্যাস হিসাবে বিবেচিত হয়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. ব্যবহার reduceএবংObject.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);

নোট করুন যে উপরের কোডটিতেpredicate অবশ্যই অন্তর্ভুক্তির শর্ত থাকতে হবে ( ওপি ব্যবহৃত বর্জনীয় শর্তের বিপরীতে ), যাতে এটি কীভাবে Array.prototype.filterকাজ করে তার সাথে সামঞ্জস্য থাকে।

২. (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);

৩. mapপরিবর্তে সিনট্যাক্স ব্যবহার করে এবং ছড়িয়ে দিনreduce

এখানে আমরা Object.assignকলটি লুপ থেকে সরিয়ে নিয়েছি, সুতরাং এটি কেবল একবার তৈরি করা হয়েছে এবং পৃথক যুক্তি হিসাবে ( স্প্রেড সিনট্যাক্স ব্যবহার করে ) স্বতন্ত্র কীগুলি এটি পাস করুন :

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.entriesএবংObject.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);

প্রাকটিক ফাংশনটি এখানে আর্গুমেন্ট হিসাবে একটি মূল / মান জুটি পায় যা কিছুটা আলাদা তবে প্রেডিকেট ফাংশনের যুক্তিতে আরও সম্ভাবনার অনুমতি দেয়।


এটি আরও জটিল প্রশ্ন হতে পারে? উদাহরণস্বরূপ:x => x.Expression.Filters.Filter
IamStalker

2
@ আইমস্টালকার, আপনি চেষ্টা করেছেন? এটি যতক্ষণ না আপনি দ্বিতীয় যুক্তিতে একটি বৈধ ফাংশন সরবরাহ করবেন ততক্ষণ কোনও ব্যাপার নয়। এনবি: .Filterশেষে কী আছে তা আমার কোনও ধারণা নেই তবে এটি যদি কোনও ফাংশন হয় তবে আপনাকে এটিকে কল করতে হবে ( x => x.Expression.Filters.Filter())
ট্রিনকোট

এতক্ষণ! 1 লাইনে করা যেতে পারে। এটি দেখুন
আব্দেন্নুর TOUMI

1
আরও নতুন বৈশিষ্ট্যগুলি কম কোডের জন্য তৈরি করতে পারে তবে তারা ধীর পারফরম্যান্সের জন্যও তৈরি করে । এড 3 অনুগত কোড বেশিরভাগ ব্রাউজারগুলিতে দ্বিগুণের চেয়ে দ্রুত গতিতে চলে।
রবজি


20

আপনি যদি আন্ডারস্কোর বা লড্যাশ ব্যবহার করতে ইচ্ছুক হন তবে আপনি pick(বা এর বিপরীতে omit) ব্যবহার করতে পারেন ।

আন্ডারস্কোরের ডক্সের উদাহরণ:

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

বা একটি কলব্যাক সহ ( লড্যাশের জন্য, পিকবি ব্যবহার করুন ):

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

1
লোডাশ একটি খারাপ সমাধান কারণ খালি জিনিসগুলির জন্য ফিল্টারিং সংখ্যাগুলিও সরিয়ে ফেলবে।
mibbit

আমি কেবল এর জন্য লোডাশ ব্যবহার করেছি এবং এটি একটি দুর্দান্ত সমাধান। ধন্যবাদ @ বোগদান ডি!
ইরা হারমান

@ মিবিট আপনি আরও নির্দিষ্ট হতে পারেন? আমি বিশ্বাস করি এটি কলব্যাকটি সঠিকভাবে বাস্তবায়নের বিষয়
বোগদান ডি

9

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"
  }
}

1
ভাল লাগছে! তবে কেন এটি অন্য জিনিসটি (এবং "আলিরিজা" নাম / ফিল্টারভ্যালু সহ একটি নয়) ফেরত দেয়?
পিল

1
@ পিল, ওপি এটির মতো হওয়ার জন্য বলেছে ( !predicateতাদের নিজস্ব কোড সহ নেতিবাচক ফিল্টারটি নোট করুন )।
ট্রিনকোট

7

যেমন প্যাট্রিক ইতিমধ্যে জানিয়েছে এটি একটি খারাপ ধারণা, কারণ এটি সম্ভবত আপনি যে কোনও তৃতীয় পক্ষের কোডটি ব্যবহার করতে চান তা ভঙ্গ করবে।

Jquery বা প্রোটোটাইপের মতো সমস্ত লাইব্রেরি যদি আপনি প্রসারিত করেন তবে ভেঙে যাবে Object.prototype, কারণগুলির কারণে অজস্র পুনরাবৃত্তি ( hasOwnPropertyচেক ব্যতীত) ভঙ্গ হবে কারণ আপনার যুক্ত ফাংশনগুলি পুনরাবৃত্তির অংশ হবে।


এটির কেন 'কেন' এটি পরিষ্কার ধারণা এবং সংক্ষিপ্তভাবে একটি খারাপ ধারণা বলে ব্যাখ্যা করার জন্য আপভোটড।
মাইকেল লিকুরি

5

কেমন:

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

4

প্রদত্ত

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

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

তারপরে:

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


3
এটি প্রশ্নের দ্বারা প্রয়োজনীয় কোনও প্রদত্ত প্রাকটিক ফাংশন ব্যবহার করে না।
ট্রিনকোট

4

আমি এমন একটি তৈরি করেছি Object.filter()যা কেবল কোনও ফাংশন দ্বারা ফিল্টার করে না, অন্তর্ভুক্ত করার জন্য কীগুলির একটি অ্যারে গ্রহণ করে। Alচ্ছিক তৃতীয় প্যারামিটার আপনাকে ফিল্টারকে উল্টাতে দেবে।

প্রদত্ত:

var foo = {
    x: 1,
    y: 0,
    z: -1,
    a: 'Hello',
    b: 'World'
}

এরে:

Object.filter(foo, ['z', 'a', 'b'], true);

ফাংশন:

Object.filter(foo, function (key, value) {
    return Ext.isString(value);
});

কোড

দাবি অস্বীকার : আমি ব্রেভিটির জন্য এক্সট্রা জেএস কোর ব্যবহার করতে পছন্দ করেছি। এটি প্রশ্নের অংশ না হওয়ায় বস্তুর প্রকারের জন্য টাইপ চেকার লেখার প্রয়োজন মনে করেনি।

// Helper function
function print(obj) {
    document.getElementById('disp').innerHTML += JSON.stringify(obj, undefined, '  ') + '<br />';
    console.log(obj);
}

Object.filter = function (obj, ignore, invert) {
    let result = {}; // Returns a filtered copy of the original list
    if (ignore === undefined) {
        return obj;   
    }
    invert = invert || false;
    let not = function(condition, yes) { return yes ? !condition : condition; };
    let isArray = Ext.isArray(ignore);
    for (var key in obj) {
        if (obj.hasOwnProperty(key) &&
                !(isArray && not(!Ext.Array.contains(ignore, key), invert)) &&
                !(!isArray && not(!ignore.call(undefined, key, obj[key]), invert))) {
            result[key] = obj[key];
        }
    }
    return result;
};

let foo = {
    x: 1,
    y: 0,
    z: -1,
    a: 'Hello',
    b: 'World'
};

print(Object.filter(foo, ['z', 'a', 'b'], true));
print(Object.filter(foo, (key, value) => Ext.isString(value)));
#disp {
    white-space: pre;
    font-family: monospace
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/extjs/4.2.1/builds/ext-core.min.js"></script>
<div id="disp"></div>


আমার ভ্যানিলা দয়া করে চেক করুন উত্তর এবং সারকথা
জেড Khullah

1
@ ট্রিনকোট ধন্যবাদ, আমি জায়গাটিতে ফিরে না গিয়ে বস্তুর অনুলিপি দেওয়ার জন্য প্রতিক্রিয়া আপডেট করেছি।
মিঃ পলিহর্ল

2

আমার মতামতযুক্ত সমাধান:

function objFilter(obj, filter, nonstrict){
  r = {}
  if (!filter) return {}
  if (typeof filter == 'string') return {[filter]: obj[filter]}
  for (p in obj) {
    if (typeof filter == 'object' &&  nonstrict && obj[p] ==  filter[p]) r[p] = obj[p]
    else if (typeof filter == 'object' && !nonstrict && obj[p] === filter[p]) r[p] = obj[p]
    else if (typeof filter == 'function'){ if (filter(obj[p],p,obj)) r[p] = obj[p]}
    else if (filter.length && filter.includes(p)) r[p] = obj[p]
  }
  return r
}

পরীক্ষার কেস:

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

objFilter(obj, 'a') // returns: {a: 1}
objFilter(obj, ['a','b']) // returns: {a: 1, b: 2}
objFilter(obj, {a:1}) // returns: {a: 1}
objFilter(obj, {'a':'1'}, true) // returns: {a: 1}
objFilter(obj, (v,k,o) => v%2===1) // returns: {a: 1, c: 3}

https://gist.github.com/bernardoadc/872d5a174108823159d845cc5baba337


1

আপনি যদি নতুন একটি তৈরির পরিবর্তে একই বস্তুকে পরিবর্তন করতে চান।

নিম্নলিখিত উদাহরণটি সমস্ত 0 বা খালি মান মুছে ফেলবে:

const sev = { a: 1, b: 0, c: 3 };
const deleteKeysBy = (obj, predicate) =>
  Object.keys(obj)
    .forEach( (key) => {
      if (predicate(obj[key])) {
        delete(obj[key]);
      }
    });

deleteKeysBy(sev, val => !val);

1

2020 সাল থেকে ভ্যানিলা জেএসে সমাধান।


let romNumbers={'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}

আপনি romNumbersকী দ্বারা অবজেক্ট ফিল্টার করতে পারেন :

const filteredByKey = Object.fromEntries(Object.entries(romNumbers).filter(([key, value]) => key === 'I'))
// filteredByKey = {I: 1} 

অথবা romNumbersমান অনুসারে ফিল্টার করুন :

 const filteredByValue = Object.fromEntries(Object.entries(romNumbers).filter(([key, value]) => value === 5))
 // filteredByValue = {V: 5} 

0

সবাই বলেছে, প্রোটোটাইপ দিয়ে স্ক্রু করবেন না। পরিবর্তে, কেবল এটি করার জন্য একটি ফাংশন লিখুন। এখানে আমার সংস্করণটি রয়েছে lodash:

import each from 'lodash/each';
import get from 'lodash/get';

const myFilteredResults = results => {
  const filteredResults = [];

  each(results, obj => {
    // filter by whatever logic you want.

    // sample example
    const someBoolean = get(obj, 'some_boolean', '');

    if (someBoolean) {
      filteredResults.push(obj);
    }
  });

  return filteredResults;
};

0

আমার যখন প্রয়োজন হয় তখন আমি এটি ব্যবহার করি:

const filterObject = (obj, condition) => {
    const filteredObj = {};
    Object.keys(obj).map(key => {
      if (condition(key)) {
        dataFiltered[key] = obj[key];
      }
    });
  return filteredObj;
}

-1

এই ক্ষেত্রে আমি jquery ma। ম্যাপ ব্যবহার করি, যা বস্তুগুলি পরিচালনা করতে পারে। অন্যান্য উত্তরে উল্লিখিত হিসাবে, নেটিভ প্রোটোটাইপগুলি পরিবর্তন করা ভাল অভ্যাস নয় ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_t__tototype_chain#Bad_practice_Existance_of_native_prototypes )

নীচে কেবলমাত্র আপনার অবজেক্টের কিছু সম্পত্তি পরীক্ষা করে ফিল্টারিংয়ের একটি উদাহরণ দেওয়া আছে। আপনার শর্তটি সত্য হলে এটি নিজস্ব বস্তুটি ফেরত দেয় বা undefinedযদি না দেয় তবে ফিরে আসে । undefinedসম্পত্তি যে রেকর্ড আপনার বস্তুর তালিকা থেকে অদৃশ্য হয়ে করতে হবে;

$.map(yourObject, (el, index)=>{
    return el.yourProperty ? el : undefined;
});

1
$.mapকোনও অবজেক্ট নিতে পারে তবে এটি একটি অ্যারে ফেরত দেয়, তাই মূল সম্পত্তির নামগুলি হারিয়ে যায়। ওপিতে একটি ফিল্টারযুক্ত প্লেইন অবজেক্ট দরকার।
ট্রিনকোট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.