简体   繁体   中英

Flattening a list of object properties

I'm finding it difficult to write this code in a functional style after years of working with an imperative mindset.

Given an input like:

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

The output should be:

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

How would one write this in a functional style in javascript?

First let's create a function which given an object returns an array of frames:

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

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

Next we create a concat function:

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

Finally we do the transformation:

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

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

See the demo for yourself:

 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); }

Isn't functional programming fun?


An explanation:

  1. The toFrames function takes a object (for example { id: "foo", frames: ["bar", "baz"] } ) and returns the list of frame objects (ie [{ foo: "bar" }, { foo: "baz" }] ).
  2. The concat function just concatenates two arrays. The .reduce(concat) method call flatttens arrays like [[a,b],[c,d]] to [a,b,c,d] .
  3. Given an input list of objects, we first convert each object into a list of frames, resulting in a list of list of frame objects.
  4. We then flatten the nested list to produce the desired output.

Simple.

You can do it this way supposing arr is the input

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
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM