使用地图

时间:2016-12-08 19:35:55

标签: javascript arrays dictionary functional-programming higher-order-functions

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(数组)返回正确的东西但是我也尝试了返回max(arrays [x])来强调我想要遍历整个数组的参数。 return max(arrays)==&gt; [3,3,3],返回一个数组中最大的数字3次,我也不明白为什么。

5 个答案:

答案 0 :(得分:2)

您需要从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]]));

答案 1 :(得分:2)

您的代码基于错误的构建块(each),因此其余代码会受到影响。我的回答将以更好的构建块reduce(又名foldLeft)开始,并向您展示如何从那里建立起来。

你会注意到这个答案是我们将每个功能分解为非常简单的部分,然后使用higher-order functions将所有内容放在一起。

  • 避免使用限制我们影响副作用的each
  • 无需检查Array.isArray
  • 没有命令式样式for - 使用可变迭代器循环,i
  • 无需检查数组.length属性

我强烈建议您逐步完成对此代码的评估,并了解所有部分的工作原理。如果您能够理解这些程序是如何工作的,那么您将很好地掌握一些最重要的函数式编程基础知识:recursionimmutabilityreferential transparencyhigher-order functionscurryingfunction composition

ES6提供了arrow functionsdestructuring assignmentspread syntax,这使得使用JavaScript编写功能性程序变得轻而易举 - 首先,它会让您感觉完全不同。我会在这个片段下方提供ES6之前的版本。

相关: What do multiple arrow functions mean in 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(几乎)工作原理相同。我们可以使用JavaScript编写reduce并免费获取其余内容!

还有一件事。 JavaScript的reduce需要binary function,但我们程序的其余部分期望curry函数(unary functions的序列)。为了解决这个问题,我们首先会制作一个小uncurry combinator以使所有内容适合

// 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来实现无数其他功能?其中一些包括:filterfindsomeeverykeysentries

额外学分2

Extra Credit 1 中提到的某些功能应该short-circuit,以便在到达阵列结束之前返回最终答案。哪些可以短路?我们如何重写reduce以促进这种早退行为呢?

答案 2 :(得分:0)

你试过return max(x);吗?我想这可能就是你想要的。此外,javascript中还有一个Max(),因此您无需定义它:

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

答案 3 :(得分:0)

您不需要为大多数这些功能推出自己的实现。将Math.maxArray#map结合使用,如下所示:

&#13;
&#13;
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]
&#13;
&#13;
&#13;

答案 4 :(得分:0)

您可以合并(defn f [a b c] {:a a :b b :c c}) map个功能:

reduce