2014-11-01 8 views
6

Ho questo codice che usa un lodash _.chain. Vorrei semplificare il codice, non usare lodash e farlo in un altro modo.C'è un modo per sostituire questo codice di lodash _.chain con javascript nei browser moderni?

examObjectives = _.chain(objectives) 
    .where({ 'examId': exam }) 
    .uniq(true, 'id') 
    .map(function (s): any { return { id: s.id, text: s.text, numberAndText: s.numberAndText }; }) 
    .value(); 

Qualcuno può darmi qualche consiglio su come avrei potuto togliere la dipendenza lodash, il _.chain e il codice presente sfruttare al massimo le funzioni JavaScript disponibili che possono ora essere trovati in nuovi browser. Nota Vorrei utilizzare il integrato nel filtro e le funzioni della mappa e non utilizzare alcuna funzione esterna per creare gli obiettivi di examObjectives.

Spero che qualcuno possa venire con alcune idee. Non ho molta familiarità con javascript quindi accolgo con piacere la possibilità di imparare.

+0

@elclanrs risposta è con 'filtro' e 'mappare' e soddisfa la soluzione 'moderno browser' che stai cercando. –

+0

@PatrickKlug - la soluzione elclanrs utilizza le proprie funzioni di filtro. Stavo parlando delle funzioni di filtro integrate. –

+0

utilizza le funzioni incorporate [] .filter() e [] .map. l'unica cosa che fa è avvolgerla nella sua stessa funzione in modo da poterla usare per mettere insieme le cose. –

risposta

6

ho messo insieme un po 'di roba, e il codice simile a questo:

objectives.filter(function (x) { 
    return x.examId == exam; 
}).reduce(function (accumulator, current) { 
    if (!accumulator.some(function (x) { return x.id == current.id; })) { 
     accumulator.push(current); 
    } 
    return accumulator; 
}, []).map(function (x) { 
    return { 
     id: x.id, 
     text: x.text, 
     numberAndtext: x.numberAndText 
    } 
}); 

(" uniquifier "ispirato a https://stackoverflow.com/a/17903018/2022183).

È possibile ridurre questo codice estraendo il confronto di un immobile per un valore costante con una funzione come questa:

function propertyEqualTo(prop, val) { 
    return function (x) { 
     return x[prop] == val; 
    }; 
} 

e il codice sarà letto:

return objectives.filter(propertyEqualTo('examId', exam)).reduce(function (accumulator, current) { 
    if (!accumulator.some(propertyEqualTo('id', current.id)) { 
     accumulator.push(current); 
    } 
... 

Sei sicuro che hai bisogno della chiamata uniq() qui comunque? Stai cercando uno id che dovrebbe essere unico fin dall'inizio. Se sei stato in grado di rimuovere questa chiamata, il tuo codice dovrebbe essere molto breve.

+0

Grazie per i vostri suggerimenti.Guarderò attentamente nella soluzione che hai proposto e proveremo presto. –

6

È possibile iniziare a definire funzioni regolari, che prendono il ricevitore ultima per convenienza, per esempio:

var map = function(f, xs) { 
    return xs.map(f) 
} 

var filter = function(f, xs) { 
    return xs.filter(f) 
} 

Poi si può costruire chain utilizzando l'oggetto arguments:

var methods = {map: map, filter: filter} 

var chain = function(xs) { 
    return Object.keys(methods).reduce(function(acc, k) { 
    acc[k] = function() { 
     var as = [].slice.call(arguments) 
     return methods[k].apply(this, as.concat([xs])) 
    } 
    return acc 
    },{}) 
} 

ora si può fare :

filter(even, map(plus1, [1,2,3])) //=> [2,4] 

Così come:

chain([1,2,3]).map(plus1).filter(even) //=> [2,4] 

E se sono stati al curry le funzioni, si può anche esprimere come:

var chain = compose(filter(even), map(plus1)) 
chain([1,2,3]) //=> [2,4] 
+0

C'è un modo che potrei abbreviare ulteriormente utilizzando la mappa javascript e le funzioni di filtro? Scusa avrei dovuto accennare prima, ma il mio amico ha sottolineato che queste funzioni potrebbero renderlo più facile. –

-1

Tutte le seguenti funzioni one-trick sono state prese da mofun.js, qualcosa che ho scritto per essere come lodash, ma completamente modulare (non interno dipende dai metodi) e che ha sfruttato appieno i metodi nativi.

// mofun.js-provided stock utility stand-alone functions: 
function where(o,_,__){var t=this;return Object.keys(t).every(function(k,_,__){return o[k]===t[k];});} 
function extract(o,_,__){return o[""+this];} 
function extractObject(o,_,__){var o2={};this.forEach(function(t,_,__){return o2[t]=o[t];});return o2;} 
function groupBy(r,s){var ret={};r.forEach(function(a,_,__){var k=a[s],b=ret[k]||(ret[k]=[]);b.push(a);});return ret;} 
function obVals(o){var t=[],n=0;for(var r in o)o.hasOwnProperty(r)&&(t[n++]=o[r]);return t;} 

// begin custom code: 
obVals(// temp object back into array of values 
    groupBy(// group array of objects into a grouped temp object of arrays 
    objectives.filter(where, { 'examId': exam }) // only objects with the proper examId 
    , "id") // groupBy using "id" peoperty of each object 
) 
.map(extract, 0) //take first value of each group's array to get unique ids among result objects 
.map(extractObject, ["id", "text", "numberAndText"]) // extract some properties into a blank object 

il codice rimane molto simile a lodash, ad eccezione della parte di trovare oggetti unici sulla base di una sub-struttura (anziché dell'intero oggetto confronto), che ho compiuto raggruppando da tale struttura, poi strappando la primo elemento di ciascun gruppo; regolare secondo necessità.

1

Dipende da cosa si vuole veramente fare.

volete sapere come implementare funzioni lodash utilizzate con

Utilizzare le soluzioni proposte moderna API del browser in questo argomento.

si desidera rimuovere la dipendenza da lodash

Se questo è il caso, immagino che si desidera di pubblicare una libreria libera-dipendenza.

Nota che Underscore e Lodash sono entrambi sotto MIT license e quindi puoi semplicemente copiare/incollare le funzioni necessarie e inserirle direttamente nella tua app/lib/qualunque.

volete buona performance

Basta essere consapevoli del fatto che l'utilizzo di browser moderno API non è sempre il modo per ottenere le migliori prestazioni. Javascript ora è molto veloce (a meno che tu non manipoli direttamente il DOM, controlla le presentazioni ReactJS) ed è spesso più veloce usare il codice JS progettato in modo efficiente rispetto al codice nativo mal progettato. Inoltre, non tutte le funzioni API del browser sono implementate con codice nativo.

Concatenando le istruzioni di sottolineatura, in ogni fase viene creato un array intermedio, con conseguente maggiore consumo di memoria e attività di garbage collection. In base alle dimensioni della matrice iniziale, potrebbe influire sulle prestazioni della tua app e potrebbe essere preferibile utilizzare il codice imperativo.

Una tecnica moderna per gestire queste allocazioni di array intermedie mantenendo uno stile di programmazione funzionale consiste nell'utilizzare i trasduttori . Si Seels ci sono 2 principali implementazioni JS per ora:

Questo può essere considerato come un'ottimizzazione prematura per piccoli array, ma in realtà trasduttori non sono molto complicate e non fa introdurre quella molta complessità. Se vuoi sentirti a casa puoi anche usare underscore-tranceducers che offre un'API molto simile a Underscore.

+0

Ricorda che _.map() è più veloce di [] .map (perché funziona meno). inoltre, non è così semplice scavare sotto il trattino di sottolineatura e lodash perché hanno molte dipendenze interne, ma è possibile ottenere versioni standalone della maggior parte dei metodi dalla lib mofun.js: http://danml.com/mofun/. – dandavis

+0

Esiste anche uno strumento online per ottenere una libreria di Lodash minima con solo le funzioni necessarie, riducendo notevolmente le dimensioni del file JS. – PhiLho

+0

Lodash (nella sua versione attuale, 3+) fa il lazy chaining, evitando di creare array intermedi quando possibile. Vedere * Metodi "Catena" * nella [documentazione di Lodash] (https://lodash.com/docs). – PhiLho

0
objectives = [{ 
    id: 1, 
    text: 'hello', 
    numberAndText: 'sdfafaadsf', 
    examId: 'exam' 
}, { 
    id: 2, 
    text: 'hello', 
    numberAndText: 'sdfafaadsf', 
    examId: 'exam2' 
}]; 
var result = objectives 
    .filter(function(item) { 
     return item['examId'] === 'exam'; 
    }) 
    .map(function(item) { 
     return { 
      id: item.id, 
      text: item.text, 
      numberAndText: item.numberAndText 
     }; 
    }) 
    .reduce(function(prev, curr) { 
     var ids = prev.map(function(item) { 
      return item.id; 
     }); 
     if (ids.indexOf(curr.id) < 0) { 
      prev.push(curr); 
     } 
     return prev; 
    }, []); 

con la mappa del filtro riducono, semplice è possibile raggiungere questo obiettivo di vaniglia js

Problemi correlati