Вернуть максимальное число в каждом массиве, используя карту

function each(coll, f) {
  if (Array.isArray(coll)) {
    for (var i = 0; i < coll.length; i++) {
      f(coll[i], i);
    }
  } else {
    for (var key in coll) {
      f(coll[key], key);
    }
  }
}

function map(array, f) {
  var acc = [];
  each(array, function(element, i) {
    acc.push(f(element, i));
  });
  return acc;
}

function max(numbers) {
  var maximum = numbers[0];
  each(numbers,function(x){
    if(x>maximum){
      maximum = x;}
  });
  return maximum;
}

function maximums(arrays){
  return map(arrays, function(x){
    return max(arrays);
  })
}

maximums([1,2,3],[5,6,7])

Я не совсем понимаю карту. Я написал максимальное число в функции массива с каждым, и я хочу реализовать это для отображения. Я знаю, что возвращаю не то, что нужно, с помощью return max(arrays), но я также пробовал return max(arrays[x]), чтобы подчеркнуть, что я хочу перебрать весь аргумент массивов. return max(arrays) ==> [3,3,3], возвращает наибольшее число в одном массиве 3 раза, что я тоже не понимаю, почему.


comment
Хм, почему бы не просто var arrs = [[1,2,3],[5,6,7]], maxes = arrs.map(a => Math.max(...a)); console.log(maxes);?   -  person Redu    schedule 08.12.2016
comment
потому что это был класс, и мне пришлось все разбить и убедиться, что я понимаю абстракцию этого, прежде чем я буду делать это стенографически в будущем :)   -  person heliu    schedule 08.12.2016
comment
Приведенный выше код не является сокращением. В 2016 году это абстракция, о которой вы должны думать в классе JS для этой работы. Но хорошо, я понял вашу точку зрения.   -  person Redu    schedule 08.12.2016


Ответы (5)


Вам нужно получить максимум от x

function maximums(arrays) {
    return map(arrays, function (x) {
        return max(x);
        //         ^                         
    });
}

И вызовите функцию с массивом массивов

maximums([[1, 2, 3], [5, 6, 7]]);
//       ^                    ^

function each(coll, f) {
    if (Array.isArray(coll)) {
        for (var i = 0; i < coll.length; i++) {
            f(coll[i], i);
        }
    } else {
        for (var key in coll) {
            f(coll[key], key);
        }
    }
}

function map(array, f) {
    var acc = [];
    each(array, function (element, i) {
        acc.push(f(element, i));
    });
    return acc;
}

function max(numbers) {
    var maximum = numbers[0];
    each(numbers, function (x) {
        if (x > maximum) {
            maximum = x;
        }
    });
    return maximum;
}

function maximums(arrays) {
    return map(arrays, function (x) {
        return max(x);
    })
}

console.log(maximums([[1, 2, 3], [5, 6, 7]]));

person Nina Scholz    schedule 08.12.2016
comment
тьфу, return max(x) был тем, что у меня было в начале. я только что назвал функцию неправильно! Благодарность!! - person heliu; 08.12.2016

Ваш код основан на плохом строительном блоке (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

Вы пробовали return max(x);? Я думаю, это может быть то, что вы хотите. Также в javascript есть Max(), поэтому вам не нужно его определять:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max

person Alex G Rice    schedule 08.12.2016
comment
Я пробовал вернуть max(x), и он возвращает [undefined, undefined, undefined]. и я знаю о math.max. я просто пытаюсь научиться использовать карту по-разному - person heliu; 08.12.2016
comment
Подожди, ты прав. мне нужно вызвать его в одном массиве. шшшш - person heliu; 08.12.2016
comment
› Метод map() создает новый массив с результатами вызова предоставленной функции для каждого элемента этого массива. developer.mozilla.org/en-US/ docs/Web/JavaScript/Reference/ Надеюсь, это поможет :) - person Alex G Rice; 08.12.2016

Для большинства этих функций вам не нужно накатывать собственную реализацию. Используйте Math.max в сочетании с Array#map. как это:

function maximum (array) {
    return Math.max.apply(null, array)
}

console.log(
    [[1,2,3], [5,6,7]].map(maximum)
) //=> [3, 7]
    
// if you still want a `maximums` function
function maximums (arrays) {
    return arrays.map(maximum)
}

console.log(
    maximums([[1,2,3], [5,6,7]]))
) //=> [3, 7]

person gyre    schedule 08.12.2016

Вы можете комбинировать функции map и reduce:

function maximums(x) {
    return x.map(function(y){
        return y.reduce(function(a,b){ return Math.max(a,b); });
    });
}
person José Antonio Riaza Valverde    schedule 08.12.2016