Ваш код основан на плохом строительном блоке (each
), и поэтому остальная часть вашего кода страдает от последствий. Мой ответ начнёт с лучшего строительного блока, reduce
(также известного как foldLeft
), и покажет вам, как наращивать его.
Что вы заметите в этом ответе, так это то, что мы разбиваем каждую функцию на очень простые части, а затем используем функции высшего порядка, чтобы собрать все воедино.
- избегайте использования
each
, что ограничивает нас побочными функциями
- нет необходимости проверять
Array.isArray
- нет императивного стиля
for
-циклов с изменяемыми итераторами, i
- нет необходимости проверять свойство массива
.length
Я настоятельно рекомендую вам выполнить оценку этого кода и посмотреть, как работают все его части. Если вы сможете понять, как работает любая из этих программ, вы будете на пути к освоению некоторых наиболее важных основ функционального программирования: рекурсия, неизменяемость, прозрачность ссылок, функции высшего порядка, каррирование и композиция функций†
ES6 предлагает стрелочные функции, назначение деструктурирования и расширенный синтаксис, который упрощает написание функциональных программ на JavaScript, хотя при чтении они будут ощущаться совершенно по-другому. , во-первых. Ниже этого фрагмента я предложу pre-ES6.
Связано: Что означают несколько функций со стрелками в JavaScript?
// reduce is your new, gold-standard building block
const reduce = f => y => ([x,...xs]) => {
if (x === undefined)
return y
else
return reduce (f) (f (y) (x)) (xs)
}
// derive map from reduce
const map = f => reduce (acc => x => [...acc, f(x)]) ([])
// get max of 2 numbers
const max = x => y => x > y ? x : y
// get max of a list of numbers
const maximum = reduce (max) (-Infinity)
// get each max of a list of a list of numbers
const maximums = map (maximum)
// see the result of your hard work
console.log(maximums ([ [ 1, 3, 2 ], [ 7, 5, 6 ] ]))
// => [ 3, 7 ]
Если вы боретесь с кодом выше, этот код (ниже) написан на ES5 (точнее, до ES6). Более знакомый синтаксис может помочь вам, пока вы еще только начинаете резать зубы. В ES5 это более подробно, но работает (почти) идентично.
// reduce is your new, gold-standard building block
function reduce (f) {
return function (y) {
return function (xs) {
if (xs.length === 0)
return y
else
return reduce (f) (f (y) (xs[0])) (xs.slice(1))
}
}
}
// derive map from reduce
function map (f) {
return reduce (function (acc) {
return function (x) {
return acc.concat([ f(x) ])
}
}) ([])
}
// get max of 2 numbers
function max (x) {
return function (y) {
return x > y ? x : y
}
}
// get max of a list of numbers
var maximum = reduce (max) (-Infinity);
// get each max of a list of a list of numbers
var maximums = map (maximum);
// see the result of your hard work
console.log(maximums ([ [ 1, 3, 2 ], [ 7, 5, 6 ] ]))
// => [ 3, 7 ]
† Конечно, есть и другие основы функционального программирования, но это, безусловно, хорошее начало.
Все еще застрял?
reduce
бесспорно самая сложная функция в программах выше. Если вы боретесь с этим, мы можем немного схитрить, чтобы сократить наше понимание программы. JavaScript предлагает встроенный Array.prototype.reduce который (почти) работает одинаково. Мы могли бы написать reduce
с помощью JavaScript, а остальное получить бесплатно!
Еще одна вещь. Сокращение JavaScript предполагает бинарную функцию, но остальная часть нашей программы ожидает каррированные функции (последовательности унарные функции). Чтобы обойти это, мы сначала создадим небольшой uncurry
комбинатор, чтобы собрать все вместе.
// convert sequence of unary functions to a binary function
const uncurry = f => (x,y) => f (x) (y)
// we can cheat using JavaScript built-in reduce with uncurry
const reduce = f => y => xs => xs.reduce(uncurry(f), y)
// the rest stays the same !
// ...
// derive map from reduce
const map = f => reduce (acc => x => [...acc, f(x)]) ([])
// get max of 2 numbers
const max = x => y => x > y ? x : y
// get max of a list of numbers
const maximum = reduce (max) (-Infinity)
// get each max of a list of a list of numbers
const maximums = map (maximum)
// see the result of your hard work
console.log(maximums ([ [ 1, 3, 2 ], [ 7, 5, 6 ] ]))
// => [ 3, 7 ]
Дополнительный балл 1
Итак, я сказал вам, что reduce
– это ваш золотой стандарт. Знаете ли вы, что помимо map
вы также можете использовать reduce
для реализации множества других функций? Некоторые из них: filter
, find
, some
, every
, keys
и entries
.
Дополнительный балл 2
Некоторые функции, упомянутые в дополнительном балле 1, должны замыкаться. когда окончательный ответ может быть возвращен до достижения конца массива. Какие из них можно замкнуть накоротко? И как мы можем переписать reduce
, чтобы облегчить это поведение раннего выхода?
person
Mulan
schedule
08.12.2016
var arrs = [[1,2,3],[5,6,7]], maxes = arrs.map(a => Math.max(...a)); console.log(maxes);
? - person Redu   schedule 08.12.2016