【问题标题】:Scala's "for comprehension" in JavascriptScala 在 JavaScript 中的“理解”
【发布时间】:2014-04-10 20:55:22
【问题描述】:

我已经习惯了 Scala 的“for”结构并且非常喜欢它。我现在正在编写一些 JavaScript 代码并使用 Lodash(基本上是 Underscore 的扩展)。有没有办法在 JavaScript 中模仿 Scala 的“for”理解?

我的目标是清理类似这样的 map/reduce 代码:

var rawCoordinates = _.map( directionsRoute.legs, function ( leg ) {
   return _.map( leg.steps, function ( step ) {
      return _.map( step.path, function ( latLng ) {
         return [ latLng.lng(), latLng.lat() ];
      } );
   } );
} );
var finalCoordinates = _.flatten( rawCoordinates, true );

在代码中,我生成了[[coord1,coord2,coord3],[coord4,coord5]] 格式的坐标数组,其中每个坐标为[39.5, -106.2](它是每个 Google 地图方向步骤的坐标数组)。

在 Scala 中,同样的事情可以这样写:

val stepCoordinates:List[List[Tuple2[Number,Number]]] = for {
   leg <- legs;
   step <- leg.steps;
   path <- step.path;
   latLng <- path
} yield (latLng.lng(), latLng.lat())

谢谢!

【问题讨论】:

  • 其实scala的理解might be written like this所以会更容易理解
  • Scala 代码中不需要嵌套的for
  • 哦,好点,我修好了

标签: javascript scala underscore.js lodash


【解决方案1】:

Javascript 不能使用新的关键字或运算符进行扩展,但这些并不重要。我们可以使用通常的函数,它们可能看起来不太好,但可读性很好。下面是一个执行嵌套 for 循环的函数示例。

function deepMap(xs, path, fn) {
    function impl(xs, path, args) {
        var result = new Array(xs.length);
        if (path.length == 0) {
            for (var i = 0; i < xs.length; i++) {
                result[i] = fn.apply(null, args.concat([xs[i]]));
            }
            return result;
        } else {
            for (var i = 0; i < xs.length; i++) {
                result[i] = impl(xs[i][path[0]], path.slice(1), args.concat(xs[i]));
            }
            return result.reduce(function(x, y) {return x.concat(y)}, []);
        }
    }
    return impl(xs, path, []);
}

// for generating lat and long functions
function x(x) {return function() {return x}}

// sample data
var legs = [{
    steps: [{
        path: [{lat: x(1), lng: x(2)}]
    }, {
        path: [{lat: x(2), lng: x(3)}]
    }]
}, {
    steps: [{
        path: [{lat: x(3), lng: x(4)}]
    }, {
        path: [{lat: x(4), lng: x(5)}]
    }]
}];

// prints [ '(1, 2)', '(2, 3)', '(3, 4)', '(4, 5)' ]
console.log(deepMap(legs, ['steps', 'path'], function(leg, step, ll) {
    return "(" + ll.lat() + ", " +  ll.lng() + ")";
}));

【讨论】:

  • 实现、使用、示例输入和输出。很好的答案。
【解决方案2】:

下划线和 ES6 一起支持以下表示法,比较接近 Scala 表示法:

var stepCoordinates = _.chain(directionsRoute.legs)
.map('steps').flatten()
.map('path')
.map(path =>
    _.map(path, latLng =>
        [latLng.lng(), latLng.lat()]
    )
).value();

Lodash 也支持这一点。

【讨论】:

    猜你喜欢
    • 2019-06-02
    • 2017-03-28
    • 1970-01-01
    • 2018-05-06
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 2017-03-26
    • 2015-10-21
    相关资源
    最近更新 更多