2015-12-20 12 views
8

Wiele razy mam ten sam problem: chcę filtrować tablicę z prostym warunkiem, np. Sprawdź, czy nie/równości, większa niż, mniej niż zawiera ...Jaki jest najlepszy sposób tworzenia prostych funkcji filtru w javascript?

Mój kod wygląda następująco:

var result = [1, 2, 3, 4].filter(function(i) { 
    return i > 2; 
}); 
console.log(result); // [3, 4] 

Byłoby by miło mieć skróty do takich prostych operacji tak stworzyłem kilka pomocnicze funkcje:

function isGreaterThan(value) { 
    return function(original) { 
     return value < original; 
    } 
} 
[1, 2, 3, 4].filter(isGreaterThan(2)); // [3, 4] 

lub:

function isGreaterThan(value, original) { 
    return value < original; 
} 
[1, 2, 3, 4].filter(isGreaterThan.bind(null, 2)); // [3, 4] 

czy istnieje lepszy wa y jak to zrobić w javascript? Czy javascript ma wbudowane funkcje wspierające te proste porównania?

+1

Nie sądzę, istnieje lepszy sposób. – CoderPi

+0

Czy pytasz o wydajność lub czysty kod? (Myślę, że twój sposób jest najlepszy w czystym kodzie, ale w wydajności tradycyjna pętla może być lepsza). – caballerog

+0

Pytanie dotyczy czystego kodu – madox2

Odpowiedz

4

Madox, co już natknął jest koncepcja currying! I będziesz zadowolony, gdy usłyszysz, że wokół tego pomysłu jest wbudowany entire JavaScript community. Z Ramda kod wyglądałby następująco:

var filterSmallNumbers = filter(gte(3)); 
var smallNumbers = filterSmallNumbers([1,2,3,4,5,6]); 

I it works.

Wszystko, co zapewnia Ramda, to lista "funkcji curried helper", takich jak ta, którą pokazałeś. Jeśli wolisz curry z własnymi funkcjami pomocniczymi, możesz potrzebować funkcji pomocniczej curry, która redukuje wartość domyślną: var isGreaterThan = curry(function(a, b){ return a > b }). Ta funkcja curry jest zapewniona przez większość bibliotek narzędziowych, takich jak Underscore, Lodash lub Ramda.

+0

Dzięki, dokładnie szukałem funkcji pomocniczych, takich jak gte, eq, has, ... od Ramdy. Ale nadal nie jestem pewien, czy chcę się uczyć i korzystać z innej biblioteki, ponieważ ES6 ma wiele swoich funkcji. – madox2

+0

@ madox2 po rozpoczęciu kopania [kodu źródłowego Rambda] (https://github.com/ramda/ramda) zaczniesz natychmiast znajdować szkielety. – naomik

-4

jesteś prawie tam, tutaj jest prawidłowa:

var original = 2; 
function isGreaterThan(value) { 
    return value > original; 
} 
var result = [1, 2, 3, 4].filter(isGreaterThan); 
// result is [3, 4] 

reference

+0

To nie jest poprawne ... – epascarello

3

Rozwiążę tutaj odpowiedź @ Avaqa. Nie potrzebujesz lib, jak Rambda, aby zacząć używać curry. Możesz zacząć robić to z ES6 już dziś.

Wygląda na to, że już rozumiesz tę koncepcję. To już jest funkcja curried. (Każdy zsekwencjonowany funkcja przyjmuje tylko jeden argument)

function isGreaterThan(value) { 
    return function(original) { 
     return value < original; 
    } 
} 

Z ES6 arrow functions, to staje się dużo łatwiejsze.

const gt = x => y => y > x; 

Wskazówki, jak przewrócił operatora > do < w swojej funkcji, aby uczynić korzystanie wydają się bardziej naturalne? Jest bardzo powszechne w przypadku funkcji curry, aby najpierw wziąć operand, który jest najmniej prawdopodobny do zmiany. Z gt, myślę, że lepiej jest użyć tutaj > ponieważ jest to nazwa naszej funkcji, ale odwróć operandy. Właśnie dlatego widzisz, że zwracam y > x zamiast x > y. gt(5) zwraca funkcję y => y > 5, co jest dla mnie bardzo naturalne.

bez dalszej zwłoki, zobaczmy to działa w filter

[1,2,3,4,5,6].filter(gt(3)); //=> [4,5,6] 

Jeśli to potrzebne do pracy w środowisku ES5 można transpile go babel bardzo łatwo. Wynik powinien wyglądać bardzo znane

"use strict"; 
var gt = function gt(x) { 
    return function (y) { 
     return y > x; 
    }; 
}; 

A z tym, jesteś na progu programowania funkcjonalnego. Jest mnóstwo fajnych rzeczy do nauki. Z problemem, który omówiliśmy tutaj, myślę, że chciałbyś dowiedzieć się więcej o function composition.

Oto podstawowy skład na zaostrzenie apetytu

// filter out odd numbers 
const mod = x => y => y % x; 
const eq = x => y => y === x; 
const comp = f => g => x => f(g(x)); 
const isEven = comp (eq (0)) (mod (2)); 
[1,2,3,4,5,6].filter(isEven); //=> [2,4,6] 
+0

Jestem już zaznajomiony z ES6 i jest super. W każdym razie, dzięki za wskazówki! – madox2

Powiązane problemy