Eliminarea elementelor cu Array.map în JavaScript

Aș dori să filtrez o serie de elemente folosind funcția map() . Aici este un fragment de cod:

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

Problema este că articolele filtrate utilizează încă spațiu în matrice și aș vrea să le șterg complet.

Vreo idee?

EDIT: Mulțumesc, am uitat de filter() , ceea ce am vrut este de fapt un filter() apoi o map() .

EDIT2: Vă mulțumim pentru faptul că map() și filter() nu sunt implementate în toate browserele, deși codul meu specific nu a fost creat în browser.

0
fr hi bn
Puteți explica de ce două iterații sunt cele mai grave decât 1? Adică, 2 * O (n) este echivalent cu O (2 * n) pentru mine ...
adăugat autor Vincent Robert, sursa
Vă rugăm să luați în considerare utilizarea reduce în loc să dublați iterațiile cu map -> filter . Îmi fac griji că oamenii care vin la această întrebare vor citi în mod greșit acest lucru fără să se uite la răspunsuri și în cele din urmă să învețe că există o cale mai bună.
adăugat autor Kyle Baker, sursa
Da, 20 * 2 & 10 * 4 sunt aceleași ... Dar, în timp ce este posibil să aveți același număr de operații efectuate în cadrul funcțiilor dvs. filtru/hartă, puteți dubla numărul de apeluri funcționale pentru a face acest lucru. filtru (f) -> harta (g) vs. reduce (h). Fiecare apel în funcție implică costuri. (Da, în general neglijabil, dar hartă/filtrare/reducere sunt tipurile de funcții utilizate pe liste foarte mari, unde aceste costuri pot deveni vizibile). Voi încerca mai târziu să fac câteva teste jsperf pentru a ilustra (și verifica) și pentru a-mi actualiza răspunsul și acest comentariu în ac
adăugat autor Kyle Baker, sursa

6 răspunsuri

Trebuie să rețineți însă că Array.filter nu este acceptat în toate browserele, deci trebuie să faceți prototipul:

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

Și făcând acest lucru, puteți să prototipați orice metodă de care aveți nevoie.

0
adăugat
Dacă intenționați cu adevărat să utilizați această metodă, vă rugăm să utilizați o polifilă adecvată, sau mai bine o bibliotecă ca Modernizr . În caz contrar, veți întâlni probabil bug-uri confuze cu browsere obscure pe care nu le veți realiza până când nu vor mai fi în producție prea mult timp.
adăugat autor Kyle Baker, sursa

Nu asta face harta. Chiar doriți să Array.filter . Sau dacă doriți cu adevărat să eliminați elementele din lista originală, va trebui să o faceți imperativ cu o buclă.

0
adăugat

Ar trebui să utilizați metoda filter mai degrabă decât să o mapați dacă nu doriți să mutați elementele din matrice, în plus față de filtrare.

de exemplu.

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

[Edit: Bineînțeles că ați putea face mereu sourceArray.filter (...) map (...) pentru a filtrează și muta]

0
adăugat
map nu se muta
adăugat autor user633183, sursa
Dar puteți muta în map .
adăugat autor Joni Juhani Rautiainen, sursa

Am plasat acest răspuns aici, deoarece poliflurile distribuite pe această pagină sunt abisive

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

extind prototipurile

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
adăugat
var arr = [1,2,'xxx','yyy']

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

arr //[1, 2, "yyy"]
0
adăugat
puteți face și var arr = [1,2, "xxx", "yyy"]; arr = arr.filter (funcția (e) {return e! = "xxx"}) console.log (arr)
adăugat autor jack blank, sursa

Am scris acest răspuns acum ceva timp și opiniile mele s-au schimbat. Vă recomandăm să verificați postarea pe blog care extinde acest subiect și o explică mult mai bine. De asemenea, oferă o comparație JSperf la sfârșitul alternativelor.

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)

Ceea ce urmează este o descriere a modului în care Array.reduce() funcționează și cum poate fi folosit pentru a realiza filtrarea și harta într-o singură iterație. Dacă acest lucru este prea condensat, vă recomand să vedeți postul de blog legat mai sus, care este un intro mult mai prietenos, cu exemple și progrese clare.

Vă dați un argument care este o funcție (de obicei anonimă).

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.

Rețineți că în timp ce Array.filter() are un singur argument (o funcție), Array.reduce() are de asemenea un important al doilea argument (deși opțional): o valoare inițială pentru "memo" care va fi trecută în acea funcție anonimă primul argument și ulterior poate fi mutat și transmis între apelurile funcționale. (Dacă nu este furnizat, atunci "memo" din primul apel de funcție anonim va fi, în mod implicit, primul iteratee, iar argumentul "iteratee" va fi de fapt a doua valoare din matrice)

În cazul nostru, vom trece într-o matrice goală pentru a începe, apoi alegeți dacă să ne injectați iteratee în matricea noastră sau nu pe baza funcției noastre - acesta este procesul de filtrare.

În cele din urmă, vom returna matricea noastră în desfășurare pentru fiecare apel de funcție anonim, iar reducerea va lua acea valoare returnată și o va transmite ca argument (numit memo) la apelul său de funcție următor.

Acest lucru permite ca filtrul și harta să se întâmple într-o singură iterație, reducându-ne numărul de iterații necesare la jumătate. :)

Pentru o explicație mai completă, consultați MDN sau link-ul de mai sus. :)

Exemplul de bază al unui apel Reducere:

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

versiune mai succinta:

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

Observați că primul iterate nu a fost mai mare decât unul, și astfel a fost filtrat. De asemenea, notați inițialeleMemo, numită doar pentru a clarifica existența și a atrage atenția asupra acesteia. Încă o dată, este transmisă ca "memo" primului apel pentru funcții anonime, iar valoarea returnată a funcției anonime este transmisă ca argument "memo" funcției următoare.

Un alt exemplu de caz clasic de utilizare pentru memo ar fi returnarea celui mai mic sau cel mai mare număr într-o matrice. Exemplu:

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

Un exemplu de scriere a propriei funcții de reducere (adesea ajută la înțelegerea unor funcții ca acestea, găsesc):

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

Implementarea reală permite accesul la lucruri precum indexul, de exemplu, dar sper că acest lucru vă ajută să obțineți un simt simplu pentru esența ei.

0
adăugat
Sclipitor! Vroiam să fac așa ceva de ani de zile. A decis sa incerce si sa-si dea seama de un mod frumos si de wow, JavaScript natural!
adăugat autor jemiloii, sursa
O altă utilitate a reduce este că spre deosebire de filter + map , apelul poate fi trecut printr-un index index care este indicele matricei originale, și nu cea a filtrului.
adăugat autor congusbongus, sursa
JavaScript, România - Moldova
JavaScript, România - Moldova
328 participanți

Comunitatea Română JavaScript: github.com/js-ro Pentru confort, opriți notificările. Parteneri: @node_ro, @php_ro, @python_ro, @seo_ro, @RomaniaGroup, @ai_ro, @Grupuri_IT Offtop: @holywars_ro Joburi: @js_jobs_ro Sponsored with ❤️ by ciupacabra.com