108

Does JavaScript has similar functionality as Ruby has?

array.select {|x| x > 3}

Something like:

array.select(function(x) { if (x > 3)  return true})

6 Answers 6

168

There is Array.filter():

var numbers = [1, 2, 3, 4, 5];
var filtered = numbers.filter(function(x) { return x > 3; });

// As a JavaScript 1.8 expression closure
filtered = numbers.filter(function(x) x > 3);

Note that Array.filter() is not standard ECMAScript, and it does not appear in ECMAScript specs older than ES5 (thanks Yi Jiang and jAndy). As such, it may not be supported by other ECMAScript dialects like JScript (on MSIE).

Nov 2020 Update: Array.filter is now supported across all major browsers.

Sign up to request clarification or add additional context in comments.

Comments

21

There's also Array.find() in ES6 which returns the first matching element it finds.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

const myArray = [1, 2, 3]

const myElement = myArray.find((element) => element === 2)

console.log(myElement)
// => 2

3 Comments

this one just returns the first element found
That's not the same as Ruby's select.
Not the one requested here, but the one I was looking for. Thanks!
6

Underscore.js is a good library for these sorts of operations - it uses the builtin routines such as Array.filter if available, or uses its own if not.

http://documentcloud.github.com/underscore/

The docs will give an idea of use - the javascript lambda syntax is nowhere near as succinct as ruby or others (I always forget to add an explicit return statement for example) and scope is another easy way to get caught out, but you can do most things quite easily with the exception of constructs such as lazy list comprehensions.

From the docs for .select() (.filter() is an alias for the same)

Looks through each value in the list, returning an array of all the values that pass a truth test (iterator). Delegates to the native filter method, if it exists.

  var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
  => [2, 4, 6]

Comments

6

yo can extend your JS with a select method like this

Array.prototype.select = function(closure){
    for(var n = 0; n < this.length; n++) {
        if(closure(this[n])){
            return this[n];
        }
    }

    return null;
};

now you can use this:

var x = [1,2,3,4];

var a = x.select(function(v) {
    return v == 2;
});

console.log(a);

or for objects in a array

var x = [{id: 1, a: true},
    {id: 2, a: true},
    {id: 3, a: true},
    {id: 4, a: true}];

var a = x.select(function(obj) {
    return obj.id = 2;
});

console.log(a);

2 Comments

Your method just returns the first item that matches it does not return an array like ruby does. With a small change though it will: Array.prototype.select = function(test){ var new_array = [] for(var n = 0; n < this.length; n++) { if(test(this[n])){ new_array.push(this[n]); } } return new_array; };
@RebekahWaterbury it's still not completely like select because select will return an Enumerator if no block is given: apidock.com/ruby/Enumerable/select
4

Array.filter is not implemented in many browsers,It is better to define this function if it does not exist.

The source code for Array.prototype is posted in MDN

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp */)
  {
    "use strict";

    if (this == null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun != "function")
      throw new TypeError();

    var res = [];
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in t)
      {
        var val = t[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, t))
          res.push(val);
      }
    }

    return res;
  };
}

see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter for more details

1 Comment

at kangax.github.io/compat-table/es5/#test-Array.prototype.filter if one selects "Obsolete platforms" and then expands "Array methods", they see that "array.prototype.filter" is not supported at IE8
4

In some cases, you can also use the map function as shown below:

var celsiusValues = [22, 50, 310, 0, 80];
var kelvinValues = celsiusValues.map(function(x) { return x - 273; });
console.log(kelvinValues); //[-251, -223, 37, -273, -193]

or

var people = [ {name: 'Mary', gender: 0, age: 28 }, {name: 'Sara', gender: 0, age: 17 }, {name: 'Tom', gender: 1, age: 20 }];
var titles = people.map(function(x) { return (x.gender == 0? 'Mrs.' : 'Mr.') + x.name; });
console.log(titles); //["Mrs.Mary", "Mrs.Sara", "Mr.Tom"]

var ageVrification = people.map(function(x) { return x.age >= 18; });
console.log(ageVrification); //[true, false, true]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.