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


90

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

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

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

कोई उपाय?

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

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


क्या आप इस बारे में विस्तार से बता सकते हैं कि 2 पुनरावृत्तियां सबसे खराब क्यों हैं? मेरा मतलब है, 2 * O (n) मेरे लिए O (2 * n) के बराबर है ...
विन्सेंट रॉबर्ट

जवाबों:


105

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

जैसे।

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

[संपादित करें: बेशक आप हमेशा sourceArray.filter(...).map(...)फ़िल्टर और म्यूटेट दोनों कर सकते थे ]


3
mapम्यूट नहीं करता है
धन्यवाद

14
लेकिन आप इसमें म्यूट कर सकते हैं map
क्रेजीवॉक

इसके साथ सावधानी बरतें: जब जेएस संदर्भ को पास करता है, जब आप नक्शे के साथ कुछ बदलते हैं तो यह वस्तु को बदल देगा लेकिन एमडीएन के रूप में, मैप्स उत्परिवर्तित सरणी देता है।
alexOtano

1
सवाल यह नहीं पूछा कि फ़िल्टर कैसे करें, सवाल ने नक्शे पर हटाने का तरीका पूछा
चकाचौंध

1
@alexOtano नहीं, मानचित्र उत्परिवर्तित नहीं करता है, और उत्परिवर्तित सरणी वापस नहीं करता है। यह एक नई सरणी देता है। जैसे,x=[1,2,3];y = x.map(z => z*2);console.log(x,y);
काइल बेकर

40

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

उस ने कहा, टीएल? डॉ। यह है: यह पूरा करने के लिए कि आप क्या पूछ रहे हैं (एक फ़ंक्शन कॉल के भीतर फ़िल्टरिंग और मैपिंग), आप उपयोग करेंगेArray.reduce()

हालांकि, अधिक पठनीय और (कम महत्वपूर्ण) आमतौर पर काफी तेजी से 2 दृष्टिकोण सिर्फ फिल्टर और मानचित्र का उपयोग एक साथ करने के लिए है:

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

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


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

वह अनाम फ़ंक्शन दो मापदंडों को लेता है - एक (जैसे मानचित्र / फ़िल्टर / forEach में पारित किए गए अनाम फ़ंक्शन) पर संचालित होने के लिए पुनरावृति है। अनाम फ़ंक्शन को कम करने के लिए पारित एक और तर्क है, हालांकि, उन कार्यों को स्वीकार नहीं करते हैं, और यह वह फ़ंक्शन है जिसे फ़ंक्शन कॉल के बीच पारित किया जाएगा, जिसे अक्सर मेमो के रूप में संदर्भित किया जाता है

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

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

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

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

अधिक पूर्ण स्पष्टीकरण के लिए, एमडीएन डॉक्स (या इस उत्तर की शुरुआत में संदर्भित मेरी पोस्ट) देखें।

मूल कमी का उदाहरण:

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, [])

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

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

[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]);
        // or, more technically complete, give access to base array
        // and index to the reducer as well:
        // memo = reduceFunc(memo, this[i], i, this);
    }

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

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


2
प्रतिभाशाली! मैं सालों से ऐसा ही कुछ करना चाहता था। एक अच्छा तरीका है और वाह, प्राकृतिक जावास्क्रिप्ट का पता लगाने की कोशिश करने का फैसला किया!
जेमिलोइ

इसकी एक और उपयोगिता reduceयह है कि, filter+ के विपरीत map, कॉलबैक को एक इंडेक्स तर्क पारित किया जा सकता है जो कि मूल सरणी का सूचकांक है, न कि फ़िल्टर किए गए के।
कोन्गुसबोंगस

@KyleBaker आपके ब्लॉग पोस्ट का लिंक पृष्ठ-पर-पाया जाता है। क्या आप लिंक को अपडेट कर सकते हैं? धन्यवाद!
टिम फिलिप

10

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


6

ऐरे फिल्टर विधि

var arr = [1, 2, 3]

// ES5 syntax
arr = arr.filter(function(item){ return item != 3 })

// ES2015 syntax
arr = arr.filter(item => item != 3)

console.log( arr )


1
आप यह भी कर सकते हैंvar arr = [1,2,"xxx", "yyy"]; arr = arr.filter(function(e){ return e!="xxx" }) console.log(arr)
जैक खाली

विशाल पाठ जोड़ने के लिए आप 4 साल बाद वापस आए? शून्य से एक
धन्यवाद

@ user633183 आप किसकी बात कर रहे हैं? क्या "विशाल पाठ"? आपकी टिप्पणी अस्पष्ट है। क्या आप वाकई सही जगह पर टिप्पणी कर रहे हैं ...?
vsync

2

हालाँकि आपको ध्यान रखना चाहिए कि यह 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;
    };
}

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


2
क्या तुम सच में इस विधि polyfill का इरादा है, एक उचित polyfill की तरह एक पुस्तकालय का उपयोग करें, या बेहतर अभी तक Modernizr । अन्यथा, आप संभवतः अस्पष्ट ब्राउज़रों के साथ भ्रमित करने वाले कीड़े में भाग लेंगे, जो आपको तब तक महसूस नहीं करेंगे जब तक कि वे बहुत लंबे समय तक उत्पादन में नहीं रहे हों।
काइल बेकर

0

निम्नलिखित कथन मानचित्र फ़ंक्शन का उपयोग करके ऑब्जेक्ट को साफ करता है।

var arraytoclean = [{v:65, toberemoved:"gronf"}, {v:12, toberemoved:null}, {v:4}];
arraytoclean.map((x,i)=>x.toberemoved=undefined);
console.dir(arraytoclean);

0

मैंने सिर्फ सरणी चौराहे पर लिखा है कि सही ढंग से हैंडल भी डुप्लिकेट करता है

https://gist.github.com/gkucmierz/8ee04544fa842411f7553ef66ac2fcf0

// array intersection that correctly handles also duplicates

const intersection = (a1, a2) => {
  const cnt = new Map();
  a2.map(el => cnt[el] = el in cnt ? cnt[el] + 1 : 1);
  return a1.filter(el => el in cnt && 0 < cnt[el]--);
};

const l = console.log;
l(intersection('1234'.split``, '3456'.split``)); // [ '3', '4' ]
l(intersection('12344'.split``, '3456'.split``)); // [ '3', '4' ]
l(intersection('1234'.split``, '33456'.split``)); // [ '3', '4' ]
l(intersection('12334'.split``, '33456'.split``)); // [ '3', '3', '4' ]


0

पहले आप मानचित्र का उपयोग कर सकते हैं और पीछा करने के साथ आप फ़िल्टर का उपयोग कर सकते हैं

state.map(item => {
            if(item.id === action.item.id){   
                    return {
                        id : action.item.id,
                        name : item.name,
                        price: item.price,
                        quantity : item.quantity-1
                    }

            }else{
                return item;
            }
        }).filter(item => {
            if(item.quantity <= 0){
                return false;
            }else{
                return true;
            }
        });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.