В образовательных целях я пытался воссоздать метод Underscore.js _.reduce()
. Хотя я смог сделать это в явном стиле, используя циклы for. Но это далеко не идеально, поскольку изменяет исходный список, который был предоставлен в качестве аргумента, что опасно.
Я также понял, что создать такой метод в стиле функционального программирования сложнее, так как невозможно явно установить значение i
для цикла.
// Explicit style
var reduce = function(list, iteratee, initial) {
if (Array.isArray(list)) {
var start;
if (arguments.length === 3) {
start = initial;
for (var i = 0; i < list.length; i++) {
start = iteratee(start, list[i], i);
}
} else {
start = list[0];
for (var i = 1; i < list.length; i++) {
start = iteratee(start, list[i], i);
}
}
}
if (list.constructor === Object) {
var start;
if (arguments.length === 3) {
start = initial;
for (var key in list) {
start = iteratee(start, list[key], key);
}
} else {
start = list[Object.keys(list)[0]];
// Delete the first property to avoid duplication.
delete list[Object.keys(list)[0]];
for (var key in list) {
start = iteratee(start, list[key], key);
}
}
}
return start;
};
Что заставляет меня бороться, так это то, что когда мой reduce()
снабжен аргументом, initial
, мне нужно впоследствии либо пропустить, либо удалить первый element
или property
аргумента, list
для окончательного значения, которое будет возвращено. Потому что, если этого не сделать, будет удвоен счет первого элемента/свойства. Я не могу представить, как я мог сделать такое при создании функции в стиле функционального программирования с участием _.each()
или forEach()
.
Это мой функциональный стиль reduce()
, который частично работает. Он работает правильно, когда указано memo
(начальное значение), потому что мне не нужно пропускать первый элемент/свойство. Но это не работает правильно, когда заметка не предоставлена, потому что тогда я устанавливаю заметку либо в первый элемент, либо в свойство, и я должен иметь возможность пропустить ее во время цикла, что я не знаю, как это сделать.
// Functional style (not working without memo)
var reduce = function(list, iteratee, memo) {
var memo = memo || list[0] || list[Object.keys(list)[0]];
_.each(list, function(element, index, list){
memo = iteratee(memo, element, index, list);
});
return memo;
};
Долго искал ответы на свой вопрос в гугле. Но не смог найти. Я был бы очень признателен за ваш совет. Спасибо.
Наконец, это дополнительный код, который я придумал, который не работает, но я думаю, что он должен.
var reduce = function(list, iteratee, memo) {
var collection = list;
var accumulation;
_.each(collection, function(item){
if (arguments.length < 3) {
if (Array.isArray(collection)) {
accumulation = collection[0];
collection.shift();
accumulation = iteratee(accumulation, item);
} else {
accumulation = collection[Object.keys(collection)[0]];
delete collection[Object.keys(collection)[0]];
accumulation = iteratee(accumulation, item);
}
} else {
accumulation = memo;
accumulation = iteratee(accumulation, item);
}
});
return accumulation;
};
for
циклов? - person Mike 'Pomax' Kamermans   schedule 16.05.2015Array.prototype.reduce()
. Кроме того, ОП упомянул, что это было академическое упражнение. - person Gent   schedule 16.05.2015reduce()
. Я не использовал его, потому что хотел узнать, как он составлен, плюс я хотел, чтобы он также поддерживал объект в качестве аргумента списка. - person KyleC   schedule 17.05.2015