diff --git a/index.js b/index.js index c18b9c3..320441f 100644 --- a/index.js +++ b/index.js @@ -21,6 +21,9 @@ var result = lego.query( // Отсортируем их по возрасту (но зачем?) lego.sortBy('age', 'asc'), // Бывает только asc (от меньшего к большему) или desc (наоборот) + // Выбираем представителей одного пола + lego.filterEqual('gender', 'Женский'), + // А пол выведем только первой буквой для удобства lego.format('gender', function (value) { return value[0]; @@ -29,21 +32,23 @@ var result = lego.query( // На дачу влезет примерно 10 человек lego.limit(10) ); +console.log(result); -// Будет круто организовать две вечеринки сразу: яблочную для девушек и картофельную для парней. -var result = lego.query( - phoneBook, +// Будет круто организовать две вечеринки сразу: яблочную для девушек и картофельную для парней. - // Выбираем всех парней, которые любят картофель, и всех девушек, которые любят яблоки - lego.or( - lego.and( - lego.filterEqual('gender', 'Мужской'), - lego.filterIn('favoriteFruit', ['Картофель']) - ), - lego.and( - lego.filterEqual('gender', 'Женский'), - lego.filterIn('favoriteFruit', ['Яблоко']) - ) - ) -); +//var result = lego.query( +// phoneBook, +// +// // Выбираем всех парней, которые любят картофель, и всех девушек, которые любят яблоки +// lego.or( +// lego.and( +// lego.filterEqual('gender', 'Мужской'), +// lego.filterIn('favoriteFruit', ['Картофель']) +// ), +// lego.and( +// lego.filterEqual('gender', 'Женский'), +// lego.filterIn('favoriteFruit', ['Яблоко']) +// ) +// ) +//); diff --git a/lego.js b/lego.js index 12bbfd1..3a8a2fc 100644 --- a/lego.js +++ b/lego.js @@ -1,11 +1,21 @@ 'use strict'; // Метод, который будет выполнять операции над коллекцией один за другим -module.exports.query = function (collection /* операторы через запятую */) { +module.exports.query = function () { + var args = [].slice.call(arguments); + var collection = args.shift(); + var changedCollection = args.reduce(function (changedCollection, method) { + return method(changedCollection); + }, collection); + + return changedCollection; }; -// Оператор reverse, который переворачивает коллекцию +/** + * Возвращает функцию, которая возвращает новую коллекцию, с обратным порядком + * @returns {Function} + */ module.exports.reverse = function () { return function (collection) { var changedCollection = collection.reverse(); @@ -15,13 +25,113 @@ module.exports.reverse = function () { }; }; -// Оператор limit, который выбирает первые N записей -module.exports.limit = function (n) { - // Магия +/** + * Возвращает функцию, которая возвращает новую коллекцию, содержащую только заданные поля + * @param {Object} arguments аргументы функции + * @returns {Function} + */ +module.exports.select = function () { + var args = arguments; + + return function (collection) { + return collection.map(function (item) { + var changedItem = {}; + + for (var i = 0; i < args.length; i++) { + var fieldName = args[i]; + changedItem[fieldName] = item[fieldName]; + } + + return changedItem; + }); + } +}; + +/** + * Возвращает функцию, которая при вызове возвращает новую коллекцию, + * в которой поле c именем field содержит значение, встречающееся в массиве type + * @param {String} field + * @param {String[]} type + * @returns {Function} + */ +module.exports.filterIn = function (field, type) { + return function (collection) { + return collection.filter(function(item){ + return type.indexOf(item[field]) !== -1; + }); + }; }; -// Вам необходимо реализовать остальные операторы: -// select, filterIn, filterEqual, sortBy, format, limit +/** + * Возвращает функцию, которая при вызове возвращает новую коллекцию, + * которая сортирует коллекцию по значеню в переданном поле + * @param {String} field имя поля по которому сортируем + * @param {String} type порядок сортировки, может быть asc или desc + * @returns {Function} + */ +module.exports.sortBy = function (field, type) { + return function (collection) { + return collection.sort(compareNumbers.bind(this, field, type)); + } +}; + +/** + * Сравнивает числа + * @param {Object} arguments аргументы функции + * @param {String} field имя поля по которому сортируем + * @param {String} type порядок сортировки + * @param {Object} a 1 объект сравнения + * @param {Object} b 2 объект сравнения + * @returns {Number} -1|0|1 + */ +function compareNumbers (field, type, a, b) { + var result = Number(a[field]) - Number(b[field]); + return type === 'desc' ? -result : result; +} + +/** + * Возвращает функцию, которая при вызове возвращает новую коллекцию, + * в которой поле (аргумент 1), равно значению (аргумент 2) + * @param {String} field + * @param {String} type + * @returns {Function} + */ +module.exports.filterEqual = function (field, type) { + return function (collection) { + return collection.filter(function(item){ + return item[field] === type; + }); + }; +}; + +/** + * Возвращает функцию, которая при вызове возвращает новую коллекцию, + * с отформатированным значением поля при помощи переданной функции + * @param {String} field + * @param {Function} fn + * @returns {Function} + */ +module.exports.format = function (field, fn) { + return function (collection) { + return collection.map(function (item) { + item[field] = fn(item[field]); + + return item; + }) + }; +}; + +/** + * Возвращает функцию, которая при вызове возвращает новую коллекцию с первыми N записями + * @param {Number} n + * @returns {Function} + */ +module.exports.limit = function (n) { + return function (collection) { + return collection.slice(0, n); + }; +}; // Будет круто, если реализуете операторы: // or и and +//реализую в следующем PR