একই সাথে একটি অ্যারে মানচিত্র এবং ফিল্টার করুন


155

আমার কাছে নতুন একটি ফিল্টার করা অ্যারে উত্পাদন করতে আমি পুনরাবৃত্তি করতে চাই এমন বস্তুর একটি অ্যারে রয়েছে। তবে এছাড়াও, আমার প্যারামিটারের উপর নির্ভর করে নতুন অ্যারে থেকে কিছু বস্তু ফিল্টার করতে হবে। আমি এটি চেষ্টা করছি:

function renderOptions(options) {
    return options.map(function (option) {
        if (!option.assigned) {
            return (someNewObject);
        }
    });   
}

এটা কি ভাল পন্থা? এর চেয়ে ভাল পদ্ধতি আর কি আছে? আমি লোডাশের মতো কোনও লাইব্রেরি ব্যবহারের জন্য উন্মুক্ত।


"অবজেক্ট.কিজ" পদ্ধতির সম্পর্কে কী? বিকাশকারী.মোজিলা.আর.জি.ফ.আর
ডকস

হ্রাস ব্যবহার করুন: বিকাশকারী.মোজিলা.আর
ইয়ভেস এম।

3
.reduce().filter(...).map(...)আমি অন্য কোথাও প্রস্তাবিত দেখেছি যা করার চেয়ে স্পষ্টতই দ্রুত । আমি প্রকট একটি JSPerf টেস্ট সেট আপ stackoverflow.com/a/47877054/2379922
জাস্টিন এল

উত্তর:


219

আপনি Array.reduceএই জন্য ব্যবহার করা উচিত ।

var options = [
  { name: 'One', assigned: true }, 
  { name: 'Two', assigned: false }, 
  { name: 'Three', assigned: true }, 
];

var reduced = options.reduce(function(filtered, option) {
  if (option.assigned) {
     var someNewValue = { name: option.name, newProperty: 'Foo' }
     filtered.push(someNewValue);
  }
  return filtered;
}, []);

document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1>
<pre id="output"> </pre>


বিকল্পভাবে, রিডুসারটি এর মতো খাঁটি ফাংশন হতে পারে

var reduced = options.reduce(function(result, option) {
  if (option.assigned) {
    return result.concat({
      name: option.name,
      newProperty: 'Foo'
    });
  }
  return result;
}, []);

2
আমার জন্য, প্রথম তর্কটি filteredএকটি অবজেক্ট। এটা filtered.pushআমার জন্য অপরিবর্তিত।
রহমতুল্লাহ এম

4
আমারও একটি বিষয় হিসাবে একটি সমস্যা ছিল filtered। এটি হ'ল কারণ আমি "প্রাথমিক মান" দিয়ে যাচ্ছিলাম না - []হ্রাস ফাংশনের পরে খালি অ্যারে ( )। যেমন ভুল var reduced = options.reduce(function(filtered, option) { ... }); সঠিক var reduced = options.reduce(function(filtered, option) { ... }, []);
জন হিগিনস

এখানে কোনও কারণ reduceনেই, আপনি forEachপ্রতিটি পুনরাবৃত্তিতে অ্যারে পরিবর্তন করার কারণে আপনি ঠিক পাশাপাশি ব্যবহার করতে পারেন filteredএবং এটি খাঁটি কার্যকর নয়। এটি ইভেন্টটি আরও পাঠযোগ্য এবং কমপ্যাক্ট হবে be
মারকো

1
@ মারকো আমি একটি খাঁটি হ্রাসকারীও প্রবর্তন করেছি। PTAL।
thefourtheye

ইয়াপ এখন খাঁটি। আপনার প্রচেষ্টার জন্য +1 আমি খাঁটি ফাংশনাল প্রোগ্রামিং অ্যাডভোকেট নই, এর থেকে খুব দূরে, আমি কেবল পয়েন্টটি দেখতে পেলাম না :) তবে আসলে আমি আপনার কৌশলটি দেখার পরেও ব্যবহার করেছি, কারণ প্রদত্ত পরিস্থিতিতে এটি এতটা কার্যকর হয়েছিল। তবে এই কাজের জন্য আপনি ফ্ল্যাটম্যাপ ফাংশনটি একবার দেখে নিতে চাইতে পারেন, আমি মনে করি আপনি উত্তরটি দেওয়ার পরে এটি স্ট্যান্ডার্ডে এসেছিল (সেই কারণে কিছু ব্রাউজার দ্বারা অসমর্থিত হতে পারে)। এটি আরও পারফরম্যান্সযুক্ত হওয়া উচিত যেহেতু এই জাতীয় সংযুক্তকরণগুলি ও (এন) টাস্কটিকে ও (এন ^ 2) এর বাইরে করে দেয়।
মার্কো

43

ব্যবহার হ্রাস, লু!

function renderOptions(options) {
    return options.reduce(function (res, option) {
        if (!option.assigned) {
            res.push(someNewObject);
        }
        return res;
    }, []);   
}

30

2019 সাল থেকে, অ্যারে.প্রোটোটাইপ.ফ্ল্যাটম্যাপটি ভাল বিকল্প।

options.flatMap(o => o.assigned ? [o.name] : []);

উপরে লিঙ্কিত MDN পৃষ্ঠা থেকে:

flatMapকোনও মানচিত্রের সময় আইটেমগুলি যুক্ত করতে এবং সরিয়ে দেওয়ার (আইটেমের সংখ্যা সংশোধন করার) উপায় হিসাবে ব্যবহার করা যেতে পারে। অন্য কথায়, এটি আপনাকে সর্বদা এক-একের পরিবর্তে অনেক আইটেমকে (প্রতিটি ইনপুট আইটেমটি পৃথকভাবে পরিচালনা করে) ম্যাপ করার অনুমতি দেয়। এই অর্থে, এটি ফিল্টারটির বিপরীতে কাজ করে। আইটেমটি রাখার জন্য কেবল একটি 1-উপাদান অ্যারে, আইটেমগুলি যুক্ত করতে একাধিক-উপাদান অ্যারে বা আইটেমটি সরাতে 0-উপাদান অ্যারেটি ফিরিয়ে দিন।


5
দুর্দান্ত সমাধান! তবে, পাঠকগণ মনে রাখবেন যে flatMapসম্প্রতি চালু হয়েছিল এবং এর ব্রাউজার সমর্থন সীমিত । আপনি অফিসিয়াল পলিফিল / শিমস: ফ্ল্যাটম্যাপ এবং ফ্ল্যাট ব্যবহার করতে পারেন ।
আরেল

24

ES6 এর সাহায্যে আপনি এটি খুব সংক্ষিপ্ত করতে পারেন:

options.filter(opt => !opt.assigned).map(opt => someNewObject)


25
ফিল্টার রিটার্নগুলি এখনও মেমরি খাইতে পারে তার উপর নির্ভর করে এটি দুটি লুপ করবে।
হোগান

1
@ হোগান তবে এটি মূল প্রশ্নের সঠিক উত্তর (অনুকূল সমাধান নাও হতে পারে)
বিক্রমভি

1
@ ভিকরামভি আপনার নোটের জন্য আপনাকে ধন্যবাদ। জিনিসটি হ'ল, আমরা প্রচুর পরিমাণে একই জিনিস অর্জন করতে পারি এবং আমি সেরাটিকে পছন্দ করি।
হোগান

10

reduceES6 অভিনব স্প্রেড সিনট্যাক্স সহ একটি লাইন এখানে!

var options = [
  { name: 'One', assigned: true }, 
  { name: 'Two', assigned: false }, 
  { name: 'Three', assigned: true }, 
];

const filtered = options
  .reduce((result, {name, assigned}) => [...result, ...assigned ? [name] : []], []);

console.log(filtered);


1
সত্যিই দুর্দান্ত @ ম্যাক্সিম! আমি এই upvote! তবে ... প্রতিটি উপাদান যুক্ত করে, এটিতে সমস্ত উপাদান ছড়িয়ে দিতে হবে result... filter(assigned).map(name)সমাধানের মতো
0zkr PM

সুন্দর. কী ঘটছে তা অনুধাবন করতে আমার এক সেকেন্ড লাগল ...assigned ? [name] : []- এটি আরও পড়ার মতো হতে পারে...(assigned ? [name] : [])
12:32

5

আমি একটি মন্তব্য করব, তবে আমার প্রয়োজনীয় খ্যাতি নেই। এটিকে আরও দক্ষ করার জন্য ম্যাক্সিম কুজমিনের অন্যথায় খুব ভাল উত্তরের একটি ছোট উন্নতি:

const options = [
  { name: 'One', assigned: true }, 
  { name: 'Two', assigned: false }, 
  { name: 'Three', assigned: true }, 
];

const filtered = options
  .reduce((result, { name, assigned }) => assigned ? result.concat(name) : result, []);

console.log(filtered);

ব্যাখ্যা

প্রতিটি পুনরাবৃত্তির জন্য পুরো ফলাফলটি বারবার ছড়িয়ে দেওয়ার পরিবর্তে আমরা কেবল অ্যারেতে সংযোজন করি এবং কেবল তখনই whenোকানোর জন্য কোনও মূল্য থাকে।



2

এক পর্যায়ে, এটি ব্যবহার করা সহজ (বা ঠিক তত সহজ) নয় forEach

var options = [
  { name: 'One', assigned: true }, 
  { name: 'Two', assigned: false }, 
  { name: 'Three', assigned: true }, 
];

var reduced = []
options.forEach(function(option) {
  if (option.assigned) {
     var someNewValue = { name: option.name, newProperty: 'Foo' }
     reduced.push(someNewValue);
  }
});

document.getElementById('output').innerHTML = JSON.stringify(reduced);
<h1>Only assigned options</h1>
<pre id="output"> </pre>

যাইহোক এটির কাজগুলি এবং ফাংশনগুলিকে একত্রিত করে এমন কোনও malter()বা fap()ফাংশন থাকলে ভাল লাগবে । এটি ফিল্টারের মতো কাজ করবে, সত্য বা মিথ্যা প্রত্যাবর্তনের পরিবর্তে এটি কোনও বস্তু বা শূন্য / অপরিজ্ঞাত ফিরিয়ে দেবে।mapfilter


আপনি আপনার মেমস চেক করতে চাইতে পারেন ... ;-)
আরেল

2

আমি নিম্নলিখিত বিষয়গুলি সহ উত্তরগুলি অনুকূল করে তুলেছি:

  1. পুনর্লিখন if (cond) { stmt; }হিসাবেcond && stmt;
  2. ES6 তীর ফাংশন ব্যবহার করুন

আমি দুটি সমাধান উপস্থাপন করব, একটি হ'ল প্রতিটি ব্যবহার করে , অন্যটি হ্রাস ব্যবহার করে :

সমাধান 1: forEach ব্যবহার করে

var options = [
  { name: 'One', assigned: true }, 
  { name: 'Two', assigned: false }, 
  { name: 'Three', assigned: true }, 
];
var reduced = []
options.forEach(o => {
  o.assigned && reduced.push( { name: o.name, newProperty: 'Foo' } );
} );
console.log(reduced);

সমাধান 2: হ্রাস ব্যবহার করে

var options = [
  { name: 'One', assigned: true }, 
  { name: 'Two', assigned: false }, 
  { name: 'Three', assigned: true }, 
];
var reduced = options.reduce((a, o) => {
  o.assigned && a.push( { name: o.name, newProperty: 'Foo' } );
  return a;
}, [ ] );
console.log(reduced);

কোন সমাধানটি নেওয়া উচিত তা স্থির করার জন্য আমি এটি আপনার উপর ছেড়ে দিয়েছি।


1
পৃথিবীতে আপনি কেন ব্যবহার করবেন cond && stmt;? এটি পড়া আরও বেশি কঠিন এবং কোনও লাভ নেই।
jlh

1

হ্রাস ব্যবহার করে, আপনি এটি একটি অ্যারে.প্রোটোটাইপ ফাংশনে করতে পারেন। এটি একটি অ্যারে থেকে সমস্ত সমান সংখ্যা আনবে।

var arr = [1,2,3,4,5,6,7,8];

var brr = arr.reduce((c, n) => {
  if (n % 2 !== 0) {
    return c;
  }
  c.push(n);
  return c;
}, []);

document.getElementById('mypre').innerHTML = brr.toString();
<h1>Get all even numbers</h1>
<pre id="mypre"> </pre>

আপনি একই পদ্ধতিটি ব্যবহার করতে পারেন এবং এটি আপনার জিনিসগুলির জন্য সাধারণকরণ করতে পারেন।

var arr = options.reduce(function(c,n){
  if(somecondition) {return c;}
  c.push(n);
  return c;
}, []);

arr ফিল্টার করা বস্তুগুলিতে এখন অন্তর্ভুক্ত থাকবে।


0

এর সরাসরি ব্যবহার .reduceপড়তে অসুবিধা হতে পারে, সুতরাং আমি এমন একটি ফাংশন তৈরি করার পরামর্শ দেব যা আপনার জন্য হ্রাসকারীকে উত্পন্ন করবে:

function mapfilter(mapper) {
  return (acc, val) => {
    const mapped = mapper(val);
    if (mapped !== false)
      acc.push(mapped);
    return acc;
  };
}

এটি এর মতো ব্যবহার করুন:

const words = "Map and filter an array #javascript #arrays";
const tags = words.split(' ')
  .reduce(mapfilter(word => word.startsWith('#') && word.slice(1)), []);
console.log(tags);  // ['javascript', 'arrays'];
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.