【问题标题】:Flattening a list of object properties展平对象属性列表
【发布时间】:2015-02-03 18:02:04
【问题描述】:

在使用命令式思维方式多年后,我发现很难以函数式风格编写此代码。

给定这样的输入:

[{'id': 'foo', frames: ['bar', 'baz']}, {'id': 'two', frames: ['three', 'four']}]

输出应该是:

[ { foo: 'bar' }, { foo: 'baz' }, { two: 'three' }, { two: 'four' } ]

如何在 javascript 中以函数式风格编写此代码?

【问题讨论】:

  • 我有这个[ { foo: 'bar' }, { foo: 'baz' } { two: 'three' }, { two: 'four' } ] 想要转换成这个 [ { foo: 'bar' , foo: 'baz' , 二: '三' , 二: '四' } ] .any 指针

标签: javascript dictionary functional-programming reduce


【解决方案1】:

假设arr 是输入,你可以这样做

result = []; // array
arr.forEach(function(o) { // go through elements
    for (var i = 0; i < o.frames.length; i++) { // make a since we need to get two objs per element
        var obj = {}; // an object which will be over written for every iteration
        obj[o.id] = o.frames[i]; // set property name and value
        result.push(obj); // finally push it in the array
    }
});

【讨论】:

  • 我不是每个人的忠实粉丝,但这是一个非常简单的解决方案!
  • 这是不正确的,这将只输出每个帧列表中的第一个值。
  • 你的编程风格不是很实用。您所做的只是将for 循环替换为forEach。在我看来,它仍然非常程序化。
  • @AaditMShah 它的工作代码更少,程序和功能是什么?这是更简洁的方式,而不是大块的代码。可以很方便的转换成函数
  • 函数式编程不仅意味着使用一流的函数进行编程,还意味着没有副作用的编程。尽管您在程序中使用了高阶函数,但仍然有副作用。将元素推送到数组是一个副作用。我无法在一条评论中解释函数式编程。最好自己学习一门像 Haskell 这样的纯函数式编程语言。这样你会更好地理解什么是函数式编程:learnyouahaskell.com
【解决方案2】:

首先让我们创建一个函数,它给定一个对象返回一个帧数组:

function toFrames(obj) {
    var id = obj.id;

    return obj.frames.map(function (frame) {
        var obj = {};
        obj[id] = frame;
        return obj;
    });
}

接下来我们创建一个concat函数:

function concat(a, b) {
    return a.concat(b);
}

最后我们进行转换:

var input = [{
    id: "foo",
    frames: ["bar", "baz"]
}, {
    id: "two",
    frames: ["three", "four"]
}];

var output = input.map(toFrames).reduce(concat);

亲自观看演示:

var input = [{
    id: "foo",
    frames: ["bar", "baz"]
}, {
    id: "two",
    frames: ["three", "four"]
}];

var output = input.map(toFrames).reduce(concat);

alert(JSON.stringify(output, null, 4));

function toFrames(obj) {
    var id = obj.id;

    return obj.frames.map(function (frame) {
        var obj = {};
        obj[id] = frame;
        return obj;
    });
}

function concat(a, b) {
    return a.concat(b);
}

函数式编程是不是很有趣?


解释:

  1. toFrames 函数接受一个对象(例如{ id: "foo", frames: ["bar", "baz"] })并返回框架对象列表(即[{ foo: "bar" }, { foo: "baz" }])。
  2. concat 函数只是连接两个数组。 .reduce(concat) 方法调用将 [[a,b],[c,d]] 等数组扁平化为 [a,b,c,d]。
  3. 给定一个输入对象列表,我们首先将每个对象转换为框架列表,从而生成框架对象列表。
  4. 然后我们将嵌套列表展平以产生所需的输出。

简单。

【讨论】:

  • 现在看就这么简单,这玩意我一定要多练。谢谢!
  • 这对我帮助很大!谢谢。
猜你喜欢
  • 2019-12-15
  • 2017-05-22
  • 2022-07-21
  • 2012-06-08
  • 2017-12-04
  • 2013-10-26
  • 1970-01-01
  • 2017-02-06
  • 2021-06-09
相关资源
最近更新 更多