0

I'm trying to group some JSON data into pairs, for a slider, but we've got a layout rule as below

Portrait | Portrait
Landscape
Portrait | Portrait
Portrait | Portrait
Landscape
Landscape

So in the gallery, 2 portrait images can be next to each other, however landscape images use a view of their own.

The data I've got follows this basic setup

var photos = [
    {
        "id": "1",
        "landscape": false
    },
    {
        "id": "2",
        "landscape": false
    },
    {
        "id": "3",
        "landscape": true
    },
    {
        "id": "4",
        "landscape": true
    },
    {
        "id": "5",
        "landscape": false
    },
    {
        "id": "6",
        "landscape": true
    },
    {
        "id": "7",
        "landscape": false
    },
    {
        "id": "8",
        "landscape": false
    },
    {
        "id": "9",
        "landscape": false
    },
    {
        "id": "10",
        "landscape": false
    },
    {
        "id": "11",
        "landscape": false
    },
    {
        "id": "12",
        "landscape": true
    },
    {
        "id": "13",
        "landscape": true
    },
    {
        "id": "14",
        "landscape": false
    },
    {
        "id": "15",
        "landscape": true
    }
];

However I need to format it in a similar structure to below - trying to keep the original order of the data as intact as possible.

var views = [
    [{id:"1", landscape: false},{id:"2", landscape: false}],
    [{id:"3", landscape: false},{id:"4", landscape: false}],
    [{id:"5", landscape: true}],
    [{id:"6", landscape: false},{id:"7", landscape: false}],
    [{id:"7", landscape: true}]
]; //etc etc

We don't have access to jQuery, but have the full _underscore.js library to hand and of course native javascript.

Could somebody please shed some light on how this would be possible?

Many thanks

owenmelbz
  • 6,180
  • 16
  • 63
  • 113
  • 1
    Are you fixing the `url` numbers in `views` now? – thefourtheye Oct 22 '14 at 19:11
  • What have you attempted so far? It seems fairly straightforward to me that you just need to loop over the single array of objects and basically "break" to a new array entry whenever you hit a "landscape: true" object. – chsh Oct 22 '14 at 19:14
  • @thefourtheye to be honest, I'm not sure what you really mean - I've adjusted the wording if that makes any more sense, its the structure I'm concerned about more than the data in it. – owenmelbz Oct 22 '14 at 19:18
  • @chsh We'll i've tried looping round as you said, then iterating a counter to determin which element to add the object to based off the length of it, and its current contents, however I ran out of ideas on as to how to do it exactly, so my last version is a bit of a mess to be honest -> http://jsfiddle.net/OwenMelbz/h72nazps/ the current method i've been playing with – owenmelbz Oct 22 '14 at 19:19
  • In your example, I wouldn't initialize the new array in views until you are sure you need it. As it stands, you'll get a bunch of extra empty Arrays() since the number of elements of photos is going to by nature be equal or greater than the number of elements in your new array. http://jsfiddle.net/h72nazps/6/ is a simple JS example (though probably not optimal). (Edited - wrong link the first time around) – chsh Oct 22 '14 at 19:36
  • To be honest, the only reason I initialised them early was to be lazy and save any undefined checks, as i could just clean the array later. However I appreciate your solution, it does seem to get the job done! Although I've now spotted another issue regarding orphan portraits, I imagine they will now need to be paired! Tonight shall be fun. – owenmelbz Oct 22 '14 at 19:49
  • @chsh I've just migrated it to underscorejs style @ http://jsfiddle.net/OwenMelbz/h72nazps/ however I've just noticed that now there is an object with 4 items in it, can you see if thats something i've changed? – owenmelbz Oct 22 '14 at 20:08

1 Answers1

1

I would try something along this:

var portraits = chunk(photos.filter(function(v) {
    return v.landscape;
}), 2);
var landscapes = photos.filter(function(v) {
    return !v.landscape;
}).map(function(v) {
    return [v];
});
var rule = [0, 1, 0, 0, 1, 1];
var result = pick(landscapes, portraits, rule);

console.log(result);

function pick(a, b, rules) {
    a = _.clone(a);
    b = _.clone(b);

    var ret = [];
    var i, rule, len;

    for (i = 0, len = a.length + b.length; i < len; i++) {
        rule = rules[i % rules.length];

        ret.push(rule ? a.pop() : b.pop());
    }

    return ret.filter(_.identity);
}

function chunk(arr, len) {
    return _.chain(arr).groupBy(function(n, i) {
        return Math.floor(i / len);
    }).pairs().pluck(1).value();
}
Juho Vepsäläinen
  • 26,573
  • 12
  • 79
  • 105
  • Thankyou for this! - Although I think I must have mislead you, by the rule i meant that simply 2 portraits can sit next to each other, but landscape must be stand-alone, rather than the 0,1,0,0,1,1 i described! – owenmelbz Oct 22 '14 at 19:48
  • Ok. Fixed it at example. Just needed to swap parameters. – Juho Vepsäläinen Oct 22 '14 at 19:51