mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-25 15:07:57 +00:00
Implemented a function filter(x, test)
This commit is contained in:
parent
d1b96cde4d
commit
f1313d8be7
@ -1,8 +1,9 @@
|
||||
# History
|
||||
|
||||
|
||||
## not yet released, version 0.27.1
|
||||
## not yet released, version 1.0.0
|
||||
|
||||
- Implemented a function `filter(x, test)`.
|
||||
- Removed `math.distribution` for now, needs some rethinking.
|
||||
- `math.number` can convert units to numbers (requires a second argument)
|
||||
- Fixed some precedence issues with the range and conversion operators.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mathjs",
|
||||
"version": "0.27.1-SNAPSHOT",
|
||||
"version": "1.0.0-SNAPSHOT",
|
||||
"main": "./dist/math.min.js",
|
||||
"ignore": [
|
||||
"coverage",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "mathjs",
|
||||
"repo": "josdejong/mathjs",
|
||||
"description": "Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser and offers an integrated solution to work with numbers, big numbers, complex numbers, units, and matrices.",
|
||||
"version": "0.27.1-SNAPSHOT",
|
||||
"version": "1.0.0-SNAPSHOT",
|
||||
"main": "dist/math.min.js",
|
||||
"keywords": [
|
||||
"math",
|
||||
|
||||
1836
dist/math.js
vendored
1836
dist/math.js
vendored
File diff suppressed because it is too large
Load Diff
2
dist/math.map
vendored
2
dist/math.map
vendored
File diff suppressed because one or more lines are too long
18
dist/math.min.js
vendored
18
dist/math.min.js
vendored
File diff suppressed because one or more lines are too long
@ -37,6 +37,7 @@
|
||||
- [exp(x)](exp.md)
|
||||
- [eye(n)](eye.md)
|
||||
- [factorial(n)](factorial.md)
|
||||
- [filter(x, test)](filter.md)
|
||||
- [fix(x)](fix.md)
|
||||
- [flatten(x)](flatten.md)
|
||||
- [floor(x)](floor.md)
|
||||
|
||||
@ -132,6 +132,7 @@
|
||||
## utils
|
||||
|
||||
- [clone(x)](clone.md)
|
||||
- [filter(x, test)](filter.md)
|
||||
- [forEach(x, callback)](forEach.md)
|
||||
- [format(value [, precision])](format.md)
|
||||
- [import(filename | object, override)](import.md)
|
||||
|
||||
@ -26,6 +26,11 @@ math.forEach([1, 2, 3], function(value) {
|
||||
```
|
||||
|
||||
|
||||
## See also
|
||||
|
||||
[filter](filter.md),
|
||||
[map](map.md),
|
||||
[sort](sort.md)
|
||||
|
||||
|
||||
<!-- Note: This file is automatically generated from source code comments. Changes made in this file will be overridden. -->
|
||||
|
||||
@ -33,6 +33,11 @@ math.map([1, 2, 3], function(value) {
|
||||
```
|
||||
|
||||
|
||||
## See also
|
||||
|
||||
[filter](filter.md),
|
||||
[forEach](forEach.md),
|
||||
[sort](sort.md)
|
||||
|
||||
|
||||
<!-- Note: This file is automatically generated from source code comments. Changes made in this file will be overridden. -->
|
||||
|
||||
14
lib/expression/docs/function/utils/filter.js
Normal file
14
lib/expression/docs/function/utils/filter.js
Normal file
@ -0,0 +1,14 @@
|
||||
module.exports = {
|
||||
'name': 'filter',
|
||||
'category': 'Utils',
|
||||
'syntax': [
|
||||
'filter(x, test)'
|
||||
],
|
||||
'description': 'Filter items in a matrix.',
|
||||
'examples': [
|
||||
'isPositive(x) = x > 0',
|
||||
'filter([6, -2, -1, 4, 3], isPositive)',
|
||||
'filter([6, -2, 0, 1, 0], x != 0)'
|
||||
],
|
||||
'seealso': ['sort', 'map', 'forEach']
|
||||
};
|
||||
@ -8,5 +8,5 @@ module.exports = {
|
||||
'examples': [
|
||||
'forEach([1, 2, 3], function(val) { console.log(val) })'
|
||||
],
|
||||
'seealso': ['unit']
|
||||
'seealso': ['map', 'sort', 'filter']
|
||||
};
|
||||
|
||||
@ -8,5 +8,5 @@ module.exports = {
|
||||
'examples': [
|
||||
'map([1, 2, 3], function(val) { return value * value })'
|
||||
],
|
||||
'seealso': []
|
||||
'seealso': ['filter', 'forEach']
|
||||
};
|
||||
|
||||
@ -8,7 +8,9 @@ module.exports = {
|
||||
'description': 'Sort the items in a matrix. Compare can be a string "asc" or "desc", or a custom sort function.',
|
||||
'examples': [
|
||||
'sort([5, 10, 1])',
|
||||
'sort(["C", "B", "A", "D"])'
|
||||
'sort(["C", "B", "A", "D"])',
|
||||
'sortByLength(a, b) = size(a)[1] - size(b)[1]',
|
||||
'sort(["Langdon", "Tom", "Sara"], sortByLength)'
|
||||
],
|
||||
'seealso': []
|
||||
'seealso': ['map', 'filter', 'forEach']
|
||||
};
|
||||
|
||||
@ -137,6 +137,7 @@ exports.to = require('./function/units/to');
|
||||
// functions - utils
|
||||
exports.clone = require('./function/utils/clone');
|
||||
exports.map = require('./function/utils/map');
|
||||
exports.filter = require('./function/utils/filter');
|
||||
exports.forEach = require('./function/utils/forEach');
|
||||
exports.format = require('./function/utils/format');
|
||||
// exports.print = require('./function/utils/print'); // TODO: add documentation for print as soon as the parser supports objects.
|
||||
|
||||
62
lib/expression/transform/filter.transform.js
Normal file
62
lib/expression/transform/filter.transform.js
Normal file
@ -0,0 +1,62 @@
|
||||
'use strict';
|
||||
|
||||
var SymbolNode = require('../../expression/node/SymbolNode');
|
||||
var isBoolean = require('../../util/boolean').isBoolean;
|
||||
var argsToArray = require('../../util/array').argsToArray;
|
||||
var ArgumentsError = require('../../error/ArgumentsError');
|
||||
|
||||
/**
|
||||
* Attach a transform function to math.filter
|
||||
* Adds a property transform containing the transform function.
|
||||
*
|
||||
* This transform adds support for equations as test function for math.filter,
|
||||
* so you can do something like 'filter([3, -2, 5], x > 0)'.
|
||||
* @param {Object} math
|
||||
*/
|
||||
module.exports = function (math) {
|
||||
var _filter = math.filter;
|
||||
|
||||
_filter.transform = function (args, math, scope) {
|
||||
if (args.length !== 2) {
|
||||
throw new ArgumentsError('filter', arguments.length, 2);
|
||||
}
|
||||
|
||||
var x = args[0].compile(math).eval(scope);
|
||||
var test;
|
||||
if (args[1] instanceof SymbolNode) {
|
||||
// a function pointer, like filter([3, -2, 5], myTestFunction);
|
||||
test = args[1].compile(math).eval(scope);
|
||||
}
|
||||
else {
|
||||
// an equation like filter([3, -2, 5], x > 0)
|
||||
|
||||
// find an undefined symbol
|
||||
var _scope = scope || {};
|
||||
var symbol = args[1]
|
||||
.find({
|
||||
type: SymbolNode
|
||||
})
|
||||
.filter(function (symbol) {
|
||||
return !(symbol.name in math) && !(symbol.name in _scope);
|
||||
})[0];
|
||||
|
||||
// create a test function for this equation
|
||||
var sub = Object.create(_scope);
|
||||
var eq = args[1].compile(math);
|
||||
if (symbol) {
|
||||
var name = symbol.name;
|
||||
test = function (x) {
|
||||
sub[name] = x;
|
||||
return eq.eval(sub);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error('No undefined variable found in filter equation');
|
||||
}
|
||||
}
|
||||
|
||||
return _filter(x, test);
|
||||
};
|
||||
|
||||
math.filter.transform.rawArgs = true;
|
||||
};
|
||||
75
lib/function/utils/filter.js
Normal file
75
lib/function/utils/filter.js
Normal file
@ -0,0 +1,75 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function (math) {
|
||||
var Matrix = require('../../type/Matrix');
|
||||
|
||||
/**
|
||||
* Sort the items in a matrix.
|
||||
*
|
||||
* Syntax:
|
||||
*
|
||||
* math.filter(x, test)
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* function isPositive (x) {
|
||||
* return x > 0;
|
||||
* }
|
||||
* math.filter([6, -2, -1, 4, 3], isPositive); // returns [6, 4, 3]
|
||||
*
|
||||
* math.filter(["23", "foo", "100", "55", "bar"], /[0-9]+/); // returns ["23", "100", "55"]
|
||||
*
|
||||
* See also:
|
||||
*
|
||||
* forEach, map, sort
|
||||
*
|
||||
* @param {Matrix | Array} x A one dimensional matrix or array to filter
|
||||
* @param {Function | RegExp} test
|
||||
* A function or regular expression to test items.
|
||||
* When `test` is a function, it must return a boolean.
|
||||
* All entries for which `test` returns true are returned.
|
||||
* @return {Matrix | Array} Returns the filtered matrix.
|
||||
*/
|
||||
math.filter = function (x, test) {
|
||||
if (arguments.length !== 2) {
|
||||
throw new math.error.ArgumentsError('filter', arguments.length, 2);
|
||||
}
|
||||
|
||||
if (x instanceof Matrix) {
|
||||
var size = x.size();
|
||||
if (size.length > 1) {
|
||||
throw new Error('Only one dimensional matrices supported');
|
||||
}
|
||||
return new Matrix(_filter(x.toArray(), test));
|
||||
}
|
||||
else if (Array.isArray(x)) {
|
||||
return _filter(x, test);
|
||||
}
|
||||
else {
|
||||
throw new math.error.UnsupportedTypeError('filter', math['typeof'](x), math['typeof'](compare));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Array} x
|
||||
* @param {function | RegExp} test
|
||||
* @return {Array} Returns the filtered array
|
||||
* @private
|
||||
*/
|
||||
function _filter(x, test) {
|
||||
if (typeof test === 'function') {
|
||||
return x.filter(function (entry) {
|
||||
return test(entry);
|
||||
});
|
||||
}
|
||||
else if (test instanceof RegExp) {
|
||||
return x.filter(function (entry) {
|
||||
return test.test(entry);
|
||||
});
|
||||
}
|
||||
else {
|
||||
throw new TypeError('Function or RegExp expected');
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -17,6 +17,10 @@ module.exports = function (math) {
|
||||
* });
|
||||
* // outputs 1, 2, 3
|
||||
*
|
||||
* See also:
|
||||
*
|
||||
* filter, map, sort
|
||||
*
|
||||
* @param {Matrix | Array} x The matrix to iterate on.
|
||||
* @param {Function} callback The callback function is invoked with three
|
||||
* parameters: the value of the element, the index
|
||||
|
||||
@ -18,6 +18,10 @@ module.exports = function (math) {
|
||||
* return value * value;
|
||||
* }); // returns [1, 4, 9]
|
||||
*
|
||||
* See also:
|
||||
*
|
||||
* filter, forEach, sort
|
||||
*
|
||||
* @param {Matrix | Array} x The matrix to iterate on.
|
||||
* @param {Function} callback The callback method is invoked with three
|
||||
* parameters: the value of the element, the index
|
||||
|
||||
@ -21,7 +21,11 @@ module.exports = function (math) {
|
||||
* }
|
||||
* math.sort(['Langdon', 'Tom', 'Sara'], sortByLength); // returns ['Tom', 'Sara', 'Langdon']
|
||||
*
|
||||
* @param {Matrix | Array} x A one dimensional matrix or array to sot
|
||||
* See also:
|
||||
*
|
||||
* filter, forEach, map
|
||||
*
|
||||
* @param {Matrix | Array} x A one dimensional matrix or array to sort
|
||||
* @param {Function | 'asc' | 'desc'} [compare='asc']
|
||||
* An optional comparator function. The function is called as
|
||||
* `compare(a, b)`, and must return 1 when a > b, -1 when a < b,
|
||||
|
||||
@ -292,6 +292,7 @@ function create (config) {
|
||||
|
||||
// functions - utils
|
||||
require('./function/utils/clone')(math, _config);
|
||||
require('./function/utils/filter')(math, _config);
|
||||
require('./function/utils/format')(math, _config);
|
||||
require('./function/utils/import')(math, _config);
|
||||
require('./function/utils/map')(math, _config);
|
||||
@ -310,6 +311,7 @@ function create (config) {
|
||||
|
||||
// attach transform functions (for converting one-based indices to zero-based)
|
||||
require('./expression/transform/concat.transform')(math, _config);
|
||||
require('./expression/transform/filter.transform')(math, _config);
|
||||
require('./expression/transform/forEach.transform')(math, _config);
|
||||
require('./expression/transform/index.transform')(math, _config);
|
||||
require('./expression/transform/map.transform')(math, _config);
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
module.exports = '0.27.1-SNAPSHOT';
|
||||
module.exports = '1.0.0-SNAPSHOT';
|
||||
// Note: This file is automatically generated when building math.js.
|
||||
// Changes made in this file will be overwritten.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mathjs",
|
||||
"version": "0.27.1-SNAPSHOT",
|
||||
"version": "1.0.0-SNAPSHOT",
|
||||
"description": "Math.js is an extensive math library for JavaScript and Node.js. It features a flexible expression parser and offers an integrated solution to work with numbers, big numbers, complex numbers, units, and matrices.",
|
||||
"author": "Jos de Jong <wjosdejong@gmail.com> (https://github.com/josdejong)",
|
||||
"contributors": [
|
||||
|
||||
@ -1084,6 +1084,26 @@ describe('parse', function() {
|
||||
approx.deepEqual(parseAndEval('to(5.08 cm * 1000, inch)'),
|
||||
math.unit(2000, 'inch').to('inch'));
|
||||
});
|
||||
|
||||
it('should evaluate function "sort" with a custom sort function', function () {
|
||||
var scope = {};
|
||||
parseAndEval('sortByLength(a, b) = size(a)[1] - size(b)[1]', scope);
|
||||
assert.deepEqual(parseAndEval('sort(["Langdon", "Tom", "Sara"], sortByLength)', scope),
|
||||
math.matrix(["Tom", "Sara", "Langdon"]));
|
||||
});
|
||||
|
||||
it('should evaluate function "filter" with a custom test function', function () {
|
||||
var scope = {};
|
||||
parseAndEval('isPositive(x) = x > 0', scope);
|
||||
assert.deepEqual(parseAndEval('filter([6, -2, -1, 4, 3], isPositive)', scope),
|
||||
math.matrix([6, 4, 3]));
|
||||
});
|
||||
|
||||
it('should evaluate function "filter" with a custom test equation', function () {
|
||||
assert.deepEqual(parseAndEval('filter([6, -2, -1, 4, 3], x > 0)'),
|
||||
math.matrix([6, 4, 3]));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
49
test/function/utils/filter.test.js
Normal file
49
test/function/utils/filter.test.js
Normal file
@ -0,0 +1,49 @@
|
||||
var assert = require('assert'),
|
||||
error = require('../../../lib/error/index'),
|
||||
math = require('../../../index');
|
||||
|
||||
describe('filter', function() {
|
||||
|
||||
it('should filter an array with a filter function', function() {
|
||||
function isPositive (x) {
|
||||
return x > 0;
|
||||
}
|
||||
assert.deepEqual(math.filter([6, -2, -1, 4, 3], isPositive), [6, 4, 3]);
|
||||
});
|
||||
|
||||
it('should filter a Matrix with a filter function', function() {
|
||||
function isPositive (x) {
|
||||
return x > 0;
|
||||
}
|
||||
assert.deepEqual(math.filter(math.matrix([6, -2, -1, 4, 3]), isPositive), math.matrix([6, 4, 3]));
|
||||
});
|
||||
|
||||
it('should filter an array with a regexp', function() {
|
||||
assert.deepEqual(math.filter(["23", "foo", "100", "55", "bar"], /[0-9]+/), ["23", "100", "55"]);
|
||||
});
|
||||
|
||||
|
||||
it('should filter a Matrix with a regexp', function() {
|
||||
assert.deepEqual(math.filter(math.matrix(["23", "foo", "100", "55", "bar"]), /[0-9]+/), math.matrix(["23", "100", "55"]));
|
||||
});
|
||||
|
||||
it('should throw an error if called with a multi dimensional matrix', function() {
|
||||
function isPositive (x) {
|
||||
return x > 0;
|
||||
}
|
||||
assert.throws(function() { math.filter(math.matrix([[6, -2],[-1, 4]]), isPositive) }, /Only one dimensional matrices supported/);
|
||||
});
|
||||
|
||||
it('should throw an error if called with unsupported type', function() {
|
||||
assert.throws(function() { math.filter(2, /regexp/) });
|
||||
assert.throws(function() { math.filter('string', /regexp/) });
|
||||
assert.throws(function() { math.filter([], 'string') });
|
||||
assert.throws(function() { math.filter([], {}) });
|
||||
});
|
||||
|
||||
it('should throw an error if called with invalid number of arguments', function() {
|
||||
assert.throws(function() { math.filter([], /reg/, 'foo') });
|
||||
assert.throws(function() { math.filter([]) });
|
||||
});
|
||||
|
||||
});
|
||||
@ -13,6 +13,7 @@ describe('sort', function() {
|
||||
});
|
||||
|
||||
it('should sort a Matrix', function() {
|
||||
assert.deepEqual(math.sort(math.matrix([5,10,1])), math.matrix([1,5, 10]));
|
||||
});
|
||||
|
||||
it('should sort an array in ascending order', function() {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user