जावास्क्रिप्ट में Array.map के साथ तत्वों को हटा रहा है

मैं map() फ़ंक्शन का उपयोग कर आइटमों की एक सरणी फ़िल्टर करना चाहता हूं। यहां एक कोड स्निपेट है:

var filteredItems = items.map(function(item)
{
    if( ...some condition... )
    {
        return item;
    }
});

समस्या यह है कि फ़िल्टर किए गए आइटम अभी भी सरणी में स्थान का उपयोग करते हैं और मैं उन्हें पूरी तरह से मिटा देना चाहता हूं।

कोई उपाय?

संपादित करें: धन्यवाद, मैं फ़िल्टर() के बारे में भूल गया था, जो मैं चाहता था वास्तव में एक फ़िल्टर() फिर map() है।

EDIT2: यह इंगित करने के लिए धन्यवाद कि map() और फ़िल्टर() सभी ब्राउज़रों में लागू नहीं किए गए हैं, हालांकि मेरा विशिष्ट कोड ब्राउज़र में चलाने का इरादा नहीं था।

0
ro fr bn
क्या आप विस्तार कर सकते हैं कि 2 पुनरावृत्तियों में सबसे खराब क्यों है? मेरा मतलब है, 2 * ओ (एन) ओ (2 * एन) के बराबर है ...
जोड़ा लेखक Vincent Robert, स्रोत
map -> फ़िल्टर के साथ पुनरावृत्ति को दोगुना करने के बजाय कृपया कम करें का उपयोग करने पर विचार करें। मुझे चिंता है कि इस प्रश्न पर आने वाले लोग गलत तरीके से जवाब देखे बिना पढ़ेंगे और आखिरकार सीखने का एक बेहतर तरीका है।
जोड़ा लेखक Kyle Baker, स्रोत
हां, 20 * 2 और 10 * 4 वही हैं ... लेकिन, जब आपके पास अपने फ़िल्टर/मैप फ़ंक्शंस में समान संख्या में ऑपरेशन हो सकते हैं, तो आप ऐसा करने के लिए फ़ंक्शन कॉल की संख्या दोगुनी कर सकते हैं। फ़िल्टर (एफ) -> मानचित्र (जी) बनाम कम (एच)। प्रत्येक फ़ंक्शन कॉल में कुछ लागत होती है। (हां, आम तौर पर नगण्य, लेकिन नक्शा/फ़िल्टर/कमी बहुत बड़ी सूचियों पर उपयोग किए जाने वाले कार्यों के प्रकार हैं, जहां वे लागत ध्यान देने योग्य हो सकती हैं)। मैं बाद में कुछ jsperf परीक्षण चलाने की कोशिश करूंगा (और सत्यापित), और उस समय मेरा उत्तर और इस टिप्पणी को अपडेट करें। (उस सब के अलावा, यह कम करने के लिए सिर्फ एक आदर्श उपयोग म
जोड़ा लेखक Kyle Baker, स्रोत

6 उत्तर

आपको नोट करना होगा कि Array.filter सभी ब्राउज़र में समर्थित नहीं है, इसलिए आपको प्रोटोटाइप करना होगा:

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.filter)
{
    Array.prototype.filter = function(fun /*, thisp*/)
    {
        var len = this.length;

        if (typeof fun != "function")
            throw new TypeError();

        var res = new Array();
        var thisp = arguments[1];

        for (var i = 0; i < len; i++)
        {
            if (i in this)
            {
                var val = this[i];//in case fun mutates this

                if (fun.call(thisp, val, i, this))
                   res.push(val);
            }
        }

        return res;
    };
}

और ऐसा करने से, आप किसी भी विधि की प्रोटोटाइप कर सकते हैं जिसकी आपको आवश्यकता हो सकती है।

0
जोड़ा
यदि आप वास्तव में इस विधि को पॉलीफिल करना चाहते हैं, तो कृपया उचित पॉलीफ़िल का उपयोग करें, या बेहतर Modernizr जैसी लाइब्रेरी का उपयोग करें। अन्यथा, आप अस्पष्ट ब्राउज़रों के साथ भ्रमित बग में भाग लेंगे जिन्हें आप तब तक महसूस नहीं करेंगे जब तक कि वे बहुत लंबे समय तक उत्पादन में नहीं रहे।
जोड़ा लेखक Kyle Baker, स्रोत

यह नक्शा नहीं करता है। आप वास्तव में Array.filter चाहते हैं। या यदि आप वास्तव में मूल सूची से तत्वों को हटाना चाहते हैं, तो आपको इसे लूप के साथ अनिवार्य रूप से करने की आवश्यकता होगी।

0
जोड़ा

जब तक आप फ़िल्टरिंग के अलावा सरणी में आइटम को म्यूटेट नहीं करना चाहते हैं, तब तक आपको मानचित्र के बजाय फ़िल्टर विधि का उपयोग करना चाहिए।

जैसे।

var filteredItems = items.filter(function(item)
{
    return ...some condition...;
});

[संपादित करें: बेशक आप हमेशा sourceArray.filter (...) कर सकते हैं। नक्शा (...) दोनों फिल्टर और उत्परिवर्तन के लिए]

0
जोड़ा
<�कोड> मानचित्र उत्परिवर्तित नहीं करता है
जोड़ा लेखक user633183, स्रोत
लेकिन आप map में बदल सकते हैं।
जोड़ा लेखक Joni Juhani Rautiainen, स्रोत

मैं इस जवाब को यहां रख रहा हूं क्योंकि इस पृष्ठ पर साझा पॉलीफिल अबाध हैं

function reduce(f, y, xs, context) {
  var acc = y;
  for (var i = 0, len = xs.length; i < len; i++)
    acc = f.call(context, acc, xs[i], i, xs);
  return acc;
}

function reduce1(f, xs, context) {
  if (xs.length === 0)
    throw Error('cannot reduce empty array without initial value');
  else
    return reduce(f, xs[0], xs.slice(1), context);
}

function map(f, xs, context) {
  return reduce(function(acc, x, i) {
    return acc.concat([
      f.call(context, x, i, xs)
    ]);
  }, [], xs);
}

function filter(f, xs, context) {
  return reduce(function(acc, x, i) {
    if (f.call(context, x, i, xs))
      return acc.concat([x]);
    else
      return acc;
  }, [], xs);
}

प्रोटोटाइप का विस्तार करें

if (Array.prototype.reduce === undefined) {
  Array.prototype.reduce = function(f, initialValue, context) {
    if (initialValue === undefined)
      return reduce1(f, this, context);
    else
      return reduce(f, initialValue, this, context);
  };
}

if (Array.prototype.map === undefined) {
  Array.prototype.map = function(f, context) {
    return map(f, this, context);
  };
}

if (Array.prototype.filter === undefined) {
  Array.prototype.filter = function(f, context) {
    return filter(f, this, context);
  };
}
0
जोड़ा
var arr = [1,2,'xxx','yyy']

arr = arr.filter(function(e){ return e != 'xxx' });

arr //[1, 2, "yyy"]
0
जोड़ा
आप var arr = [1,2, "xxx", "yyy"] भी कर सकते हैं; arr = arr.filter (फ़ंक्शन (ई) {वापसी ई! = "xxx"}) console.log (arr)
जोड़ा लेखक jack blank, स्रोत

मैंने थोड़ी देर पहले यह जवाब लिखा था, और मेरी राय बदल गई है। मैं अपने ब्लॉग पोस्ट की जांच करने की अनुशंसा करता हूं जो इस विषय को फैलाता है और यह बहुत बेहतर बताता है। यह विकल्प के अंत में एक जेएसपीआरएफ तुलना भी देता है।

The tl;dr is this: To accomplish what you're asking for (filtering and mapping within one function call), you should use Array.reduce(). However, the more readable and usually faster approach is to just use filter and map chained together:

[1,2,3].filter(num => num > 2).map(num => num * 2)

निम्नानुसार है कि कैसे Array.reduce() काम करता है, और एक पुनरावृत्ति में फ़िल्टर और मानचित्र को पूरा करने के लिए इसका उपयोग कैसे किया जा सकता है। यदि यह बहुत संघनित है, तो मैं ऊपर से जुड़े ब्लॉग पोस्ट को देखने की अत्यधिक अनुशंसा करता हूं, जो स्पष्ट उदाहरणों और प्रगति के साथ एक और अधिक अनुकूल परिचय है।

आप एक तर्क को कम करते हैं जो एक (आमतौर पर अज्ञात) फ़ंक्शन होता है।

That anonymous function takes two parameters--one (like the anonymous functions passed in to map/filter/forEach) is the iteratee to be operated on. There is another argument for the anonymous function passed to reduce, however, that those functions do not accept, and that is the value that will be passed along between function calls, often referred to as the memo.

ध्यान दें कि जबकि Array.filter() केवल एक तर्क (एक फ़ंक्शन) लेता है, Array.reduce() भी एक महत्वपूर्ण (हालांकि वैकल्पिक) दूसरा तर्क लेता है: 'ज्ञापन' के लिए प्रारंभिक मान जिसे उस अज्ञात फ़ंक्शन में पारित किया जाएगा पहला तर्क, और बाद में फंक्शन कॉल के बीच उत्परिवर्तित और पारित किया जा सकता है। (यदि यह आपूर्ति नहीं की जाती है, तो पहले अज्ञात फ़ंक्शन कॉल में 'ज्ञापन' डिफ़ॉल्ट रूप से पहला इटेटेट होगा, और 'iteratee' तर्क वास्तव में सरणी में दूसरा मान होगा)

हमारे मामले में, हम शुरू करने के लिए एक खाली सरणी में गुजरेंगे, और फिर चुनें कि हमारे एरेरेट को हमारे सरणी में इंजेक्ट करना है या हमारे फ़ंक्शन के आधार पर नहीं - यह फ़िल्टरिंग प्रक्रिया है।

अंत में, हम प्रत्येक अज्ञात फ़ंक्शन कॉल पर हमारी 'सरणी प्रगति' वापस कर देंगे, और कम करने के लिए उस वापसी मूल्य को ले जाएगा और इसे अगले कार्य कॉल में एक तर्क (ज्ञापन कहा जाता है) के रूप में पास कर देगा।

यह फिल्टर और मानचित्र को एक पुनरावृत्ति में होने की अनुमति देता है, जिससे आधे में आवश्यक पुनरावृत्तियों की संख्या कम हो जाती है। :)

अधिक पूर्ण स्पष्टीकरण के लिए, MDN </ए> या उपरोक्त लिंक। :)

कम करें कॉल का मूल उदाहरण:

let array = [1,2,3];
const initialMemo = [];

array = array.reduce((memo, iteratee) => {
   //if condition is our filter
    if (iteratee > 1) {
       //what happens inside the filter is the map
        memo.push(iteratee * 2); 
    }

   //this return value will be passed in as the 'memo' argument
   //to the next call of this function, and this function will have
   //every element passed into it at some point.
    return memo; 
}, initialMemo)

console.log(array)//[4,6], equivalent to [(2 * 2), (3 * 2)]

अधिक संक्षिप्त संस्करण:

[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])

ध्यान दें कि पहला iteratee एक से अधिक नहीं था, और इसलिए फ़िल्टर किया गया था। इसके प्रारंभिक मेमो को भी ध्यान दें, जिसका नाम सिर्फ अस्तित्व को स्पष्ट करने और इसे ध्यान में रखने के लिए किया गया है। एक बार फिर, इसे पहले ज्ञात फ़ंक्शन कॉल में 'ज्ञापन' के रूप में पारित किया जाता है, और उसके बाद अनाम फ़ंक्शन का लौटा मूल्य अगले कार्य में 'ज्ञापन' तर्क के रूप में पारित किया जाता है।

ज्ञापन के लिए क्लासिक उपयोग केस का एक और उदाहरण एक सरणी में सबसे छोटी या सबसे बड़ी संख्या लौटाएगा। उदाहरण:

[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
// ^this would return the largest number in the list.

अपना खुद का कम करने के तरीके को लिखने का एक उदाहरण (यह अक्सर इस तरह के कार्यों को समझने में मदद करता है, मुझे लगता है):

test_arr = [];

// we accept an anonymous function, and an optional 'initial memo' value.
test_arr.my_reducer = function(reduceFunc, initialMemo) {
   //if we did not pass in a second argument, then our first memo value 
   //will be whatever is in index zero. (Otherwise, it will 
   //be that second argument.)
    const initialMemoIsIndexZero = arguments.length < 2;

   //here we use that logic to set the memo value accordingly.
    let memo = initialMemoIsIndexZero ? this[0] : initialMemo;

   //here we use that same boolean to decide whether the first
   //value we pass in as iteratee is either the first or second
   //element
    const initialIteratee = initialMemoIsIndexZero ? 1 : 0;

    for (var i = initialIteratee; i < this.length; i++) {
       //memo is either the argument passed in above, or the 
       //first item in the list. initialIteratee is either the
       //first item in the list, or the second item in the list.
        memo = reduceFunc(memo, this[i]);
    }

   //after we've compressed the array into a single value,
   //we return it.
    return memo;
}

असली कार्यान्वयन इंडेक्स जैसी चीजों तक पहुंच की इजाजत देता है, उदाहरण के लिए, लेकिन मुझे उम्मीद है कि इससे आपको इसके बारे में एक जटिल अनुभव मिल जाएगा।

0
जोड़ा
प्रतिभाशाली! मैं वर्षों से ऐसा कुछ करना चाहता था। एक अच्छा और रास्ता और वाह, प्राकृतिक जावास्क्रिप्ट का प्रयास करने और समझने का फैसला किया!
जोड़ा लेखक jemiloii, स्रोत
कम करें की एक और उपयोगीता यह है कि, फ़िल्टर + map के विपरीत, कॉलबैक को एक इंडेक्स तर्क पारित किया जा सकता है जो मूल सरणी का सूचकांक है, और फ़िल्टर किए गए एक की नहीं।
जोड़ा लेखक congusbongus, स्रोत