[IMP] web: add math_utils to core

math_utils is a small library that exports two
functions:

    - cartesian: allows to compute the cartesian
                products of any numbers of arrays
                while preserving the internal
                structures of their elements.
    - sections: returns an array with all
                the initial sections of the
                array passed as parameter.
This commit is contained in:
Mathieu Duckerts-Antoine
2019-08-02 18:34:18 +00:00
parent e488f208d2
commit 5894df57d3
3 changed files with 131 additions and 0 deletions
@@ -0,0 +1,73 @@
odoo.define('web.mathUtils', function () {
"use strict";
/**
* Same values returned as those returned by cartesian function for case n = 0
* and n > 1. For n = 1, brackets are put around the unique parameter elements.
*
* @returns {Array}
*/
function _cartesian() {
var args = Array.prototype.slice.call(arguments);
if (args.length === 0) {
return [undefined];
}
var firstArray = args[0].map(function (elem) {
return [elem];
});
if (args.length === 1) {
return firstArray;
}
var productOfOtherArrays = _cartesian.apply(null, args.slice(1));
var result = firstArray.reduce(
function (acc, elem) {
return acc.concat(productOfOtherArrays.map(function (tuple) {
return elem.concat(tuple);
}));
},
[]
);
return result;
}
/**
* Returns the product of any number n of arrays.
* The internal structures of their elements is preserved.
* For n = 1, no brackets are put around the unique parameter elements
* For n = 0, the singleton [undefined] is returned since it is the unit
* of the cartesian product (up to isomorphism).
*
* @returns {Array}
*/
function cartesian() {
var args = Array.prototype.slice.call(arguments);
if (args.length === 0) {
return [undefined];
} else if (args.length === 1) {
return args[0];
} else {
return _cartesian.apply(null, args);
}
}
/**
* Returns all initial sections of a given array, e.g. for [1, 2] the array
* [[], [1], [1, 2]] is returned.
*
* @param {Array} array
* @returns {Array[]}
*/
function sections(array) {
var sections = [];
for (var i = 0; i < array.length + 1; i++) {
sections.push(array.slice(0, i));
}
return sections;
}
return {
cartesian: cartesian,
sections: sections,
};
});
@@ -0,0 +1,56 @@
odoo.define('web.math_utils_tests', function(require) {
"use strict";
var mathUtils = require('web.mathUtils');
var cartesian = mathUtils.cartesian;
QUnit.module('mathUtils', function () {
QUnit.module('cartesian');
QUnit.test('cartesian product of zero arrays', function(assert) {
assert.expect(1);
assert.deepEqual(cartesian(), [undefined],
"the unit of the product is a singleton");
});
QUnit.test('cartesian product of a single array', function(assert) {
assert.expect(5);
assert.deepEqual(cartesian([]), []);
assert.deepEqual(cartesian([1]), [1],
"we don't want unecessary brackets");
assert.deepEqual(cartesian([1, 2]), [1, 2]);
assert.deepEqual(cartesian([[1, 2]]), [[1, 2]],
"the internal structure of elements should be preserved");
assert.deepEqual(cartesian([[1, 2], [3, [2]]]), [[1, 2], [3, [2]]],
"the internal structure of elements should be preserved");
});
QUnit.test('cartesian product of two arrays', function(assert) {
assert.expect(5);
assert.deepEqual(cartesian([], []), []);
assert.deepEqual(cartesian([1], []), []);
assert.deepEqual(cartesian([1], [2]), [[1, 2]]);
assert.deepEqual(cartesian([1, 2], [3]), [[1, 3], [2, 3]]);
assert.deepEqual(cartesian([[1], 4], [2, [3]]), [[[1], 2], [[1], [3]], [4, 2], [4, [3]] ],
"the internal structure of elements should be preserved");
});
QUnit.test('cartesian product of three arrays', function(assert) {
assert.expect(4);
assert.deepEqual(cartesian([], [], []), []);
assert.deepEqual(cartesian([1], [], [2, 5]), []);
assert.deepEqual(cartesian([1], [2], [3]), [[1, 2, 3]],
"we should have no unecessary brackets, we want elements to be 'triples'");
assert.deepEqual(cartesian([[1], 2], [3], [4]), [[[1], 3, 4], [2, 3, 4]],
"the internal structure of elements should be preserved");
});
QUnit.test('cartesian product of four arrays', function(assert) {
assert.expect(1);
assert.deepEqual(cartesian([1], [2], [3], [4]), [[1, 2, 3, 4]]);
});
});
});
+2
View File
@@ -250,6 +250,7 @@
<script type="text/javascript" src="/web/static/src/js/_deprecated/data.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/context.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/data_comparison_utils.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/math_utils.js"></script>
<script type="text/javascript" src="/web/static/src/js/core/misc.js"></script>
<script type="text/javascript" src="/web/static/src/js/services/crash_manager_service.js"></script>
<script type="text/javascript" src="/web/static/src/js/services/data_manager.js"></script>
@@ -664,6 +665,7 @@
<script type="text/javascript" src="/web/static/tests/core/rpc_tests.js"></script>
<script type="text/javascript" src="/web/static/tests/core/domain_tests.js"></script>
<script type="text/javascript" src="/web/static/tests/core/data_comparison_utils_tests.js"></script>
<script type="text/javascript" src="/web/static/tests/core/math_utils_tests.js"></script>
<script type="text/javascript" src="/web/static/tests/core/mixins_tests.js"></script>
<script type="text/javascript" src="/web/static/tests/core/time_tests.js"></script>
<script type="text/javascript" src="/web/static/tests/core/concurrency_tests.js"></script>