0

I have the following javaScript object

var stats = [
    {x: 10,  y: 300, clr:'blue'},
    {x: 16,  y: 600, clr:'blue'},
    {x: 26,  y: 300, clr:'yellow'},
    {x: 36,  y: 200, clr:'yellow'},
    {x: 46,  y: 700, clr:'green'},
    {x: 56,  y: 100, clr:'green'},
];

How could I able to get the following objects? Each object seperated based on clr property The main key points are to separate and append the last object of the previous object to the first object for new object.This step is required to connect lines between.

 var stats1 = [
    {x:10,  y:300, clr:'blue'},
    {x:16,  y:600, clr:'blue'},
 ];

 var stats2 = [
    {x:16,  y:600, clr:'yellow'},
    {x:26,  y:300, clr:'yellow'},
    {x:36,  y:200, clr:'yellow'}
 ];

 var stats3 = [
    {x:36,  y:200, clr:'green'},
    {x:46,  y:700, clr:'green'},
    {x:56,  y:100, clr:'green'}
];
casillas
  • 16,351
  • 19
  • 115
  • 215
  • Can you post your code so far? – elclanrs May 11 '15 at 23:37
  • Clearly it should be "JavaScript objects", not "Java objects". – Pointy May 11 '15 at 23:37
  • "Comparing Java to JavaScript is like comparing a car to a carpet. They have nothing in common other than sounding similar." – Patrick Roberts May 11 '15 at 23:37
  • How can they both be OK? They're completely different languages! – Barmar May 11 '15 at 23:37
  • Javascript and Java are completely different language.What you are talking about is Javascript Object aren't you? – suish May 11 '15 at 23:38
  • Sorry I have fixed. It is javascript object – casillas May 11 '15 at 23:38
  • @elclanrs, I have been working on this project http://jsfiddle.net/53ygp9ut/2/ . Initially I have started with one javascript objects and Kendo-UI does not allow me to customize color property and I ended up to divide the javascript object based on their colors by doing so it works and requires this step which I am stuck. Again, key point here is to append previous last javascript object as a first javascript for new javascript – casillas May 11 '15 at 23:39
  • I don't understand the pattern. I thought you were separating them by color, but why is there a yellow in `stats3`? – Barmar May 11 '15 at 23:40
  • Sorry, My bad. I have corrected. Thanks for catching it up. – casillas May 11 '15 at 23:41
  • I fail to see how the extra yellow and green are created. – jkd May 11 '15 at 23:47
  • @jakekimds, if I do not add the last object from previous then I could not able to connect them.Imagine that each object is a line and in order to connect them your objects needs to have at least one common. I hope I am clearer. – casillas May 11 '15 at 23:48
  • 1
    Although it does not completely answer your question, [this link](http://stackoverflow.com/a/13964186/3161440) might help. – jkd May 11 '15 at 23:48
  • Yes it is partial answer. it does seperation. But I am missing the last object to append. – casillas May 11 '15 at 23:50

5 Answers5

2

Another solution as you want last object to be 1st of the next array object:

var stats = [
{x: 10,  y: 300, clr:'blue'},
{x: 16,  y: 600, clr:'blue'},
{x: 26,  y: 300, clr:'yellow'},
{x: 36,  y: 200, clr:'yellow'},
{x: 46,  y: 700, clr:'green'},
{x: 56,  y: 100, clr:'green'},
];

function groupBy( array ,prop, f )
{
  var groups = {};
  
  ///grouping & sorting
  array.forEach( function( o )
  {
    var group = JSON.stringify( f(o) );
    groups[group] = groups[group] || [];
    groups[group].push( o );  
  });
  
  var last_prop = "" ; 
  var last_elm = {} ; 
 
  for(var key in groups )
  {
    if(last_prop !== "")
    {
      
      last_elm[prop] = groups[key][0][prop] ; 
      groups[key].unshift(last_elm);
    }
    
    last_prop = key;
    last_elm = (JSON.parse(JSON.stringify(groups[key][groups[key].length - 1])));
  }
  
  return Object.keys(groups).map( function( group )
  {
    return groups[group]; 
  });
}

var result = groupBy(stats, "clr", function(item)
{
  return [item.clr];
});

console.log(result);
    document.write(JSON.stringify(result));

if it doesn't work try jsbin version http://jsbin.com/tudahibefo/1/

kwangsa
  • 1,701
  • 12
  • 16
1

var stats = [
    {x: 10,  y: 300, clr:'blue'},
    {x: 16,  y: 600, clr:'blue'},
    {x: 26,  y: 300, clr:'yellow'},
    {x: 36,  y: 200, clr:'yellow'},
    {x: 46,  y: 700, clr:'green'},
    {x: 56,  y: 100, clr:'green'},
];
var stats1 = []; // blue
var stats2 = []; // yellow
var stats3 = []; // green
var last_item = null;

for (var i = 0; i < stats.length; i++) {
  var cur_item = stats[i];
  switch (cur_item.clr) {
    case "blue":
      target = stats1;
      break;
    case "yellow":
      target = stats2;
      break;
    case "green":
      target = stats3;
      break;
  }
  if (last_item && last_item.clr != cur_item.clr) {
    // Push last item of previous colow onto new color
    target.push({
      x: last_item.x,
      y: last_item.y,
      clr: cur_item.clr
    });
  }
  target.push(cur_item);
  last_item = cur_item;

}
document.getElementById("output").innerHTML = JSON.stringify(stats1) + "<br>" + JSON.stringify(stats2) + "<br>" + JSON.stringify(stats3);
<div id="output"></div>
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Thanks a lot Barmar. It is super great! Do you think much modular code just in case you have a hundreds of colors. You initiate `var` for each objects or you wrote switch case for each case. – casillas May 11 '15 at 23:55
  • I would have used an array instead of separate variables `stats1`, `stats2`, and so on. In general, whenever you find yourself naming variables like that, you should probably be using an array instead. – Barmar May 12 '15 at 00:52
  • I just figured the answer would be easier to understand if I didn't complicate it with that change as well. I assumed if you just had three variables, you only had a fixed number of colors. – Barmar May 12 '15 at 00:53
  • Could u please provide me a modular answer if you have it now.? – casillas May 12 '15 at 01:45
  • @ilyasUyanik Are you planning on having SO write your whole application for you? It seems like you're not making any attempt to figure this out on your own, you're just posting your requirements and expecting us to do it. Surely my answer to this question should give you ideas about how to solve the other question yourself. – Barmar May 13 '15 at 17:41
1

Use filter to obtain three separate arrays:

stats1 = stats.filter(function(x){return x.clr=="blue"});
stats2 = stats.filter(function(x){return x.clr=="yellow"});
stats3 = stats.filter(function(x){return x.clr=="green"});

then add the last element of the previous array to the next one with splice

stats2.splice(0,0,stats1[stats1.length-1]);
stats3.splice(0,0,stats2[stats2.length-1]);

then change the color of the first element of arrays stats2 and stats3

stats2[0].clr="yellow";
stats3[0].clr="green";
R. Schifini
  • 9,085
  • 2
  • 26
  • 32
1

UPDATE: I've updated the solution to have the ability to connect last elements to form a link


I present a generic solution that allows you to split the array irrespective of which colors are part of the stats array.

var stats = [
    {x: 10,  y: 300, clr:'blue'},
    {x: 16,  y: 600, clr:'blue'},
    {x: 26,  y: 300, clr:'yellow'},
    {x: 36,  y: 200, clr:'yellow'},
    {x: 46,  y: 700, clr:'green'},
    {x: 56,  y: 100, clr:'green'},
];
    
// the function receives the property with which you want to divide
// in our case, it is the 'clr' property
// the 'connectLast' boolean flag is used to connect the last link
var divideArrayByProperty = function(arr, property, connectLast) {
    
    var dividedArrays = {};
    var key = null;
    var lastElement = null;
    for (var i = 0; i < arr.length; i++) {
        key = arr[i][property];
        if (undefined === dividedArrays[key]) {
            dividedArrays[key] = [];
            if (connectLast === true && i > 0) {
                lastElement = JSON.parse(JSON.stringify(arr[i-1]));
                lastElement.clr = key;
                dividedArrays[key].push(lastElement);
            }
        }
        dividedArrays[key].push(arr[i]);
    }

    return dividedArrays;
};

var result = divideArrayByProperty(stats, 'clr', true);
document.getElementById("output").innerHTML = JSON.stringify(result);
<div id='output'></div>
Software Guy
  • 3,190
  • 4
  • 21
  • 21
  • it is great solution, but it does not take into account of last element appending. It returns 2 objects for each. Please check my output in the question. I have upvoted for the great answer. – casillas May 12 '15 at 00:24
  • @ilyasUyanik I've updated the solution to have the ability to connect last elements to form a link – Software Guy May 12 '15 at 09:50
0

Yet another solution.

var stats = [
{x: 10,  y: 300, clr:'blue'},
{x: 16,  y: 600, clr:'blue'},
{x: 26,  y: 300, clr:'yellow'},
{x: 36,  y: 200, clr:'yellow'},
{x: 46,  y: 700, clr:'green'},
{x: 56,  y: 100, clr:'green'},
];

function groupWith(arr, f) {
  var result = [], group = [];
  arr.forEach(function(elem) {
    if(group.length !== 0 && !f(group[group.length - 1], elem)) {
      result.push(group);
      group = [];
    }
    group.push(elem);
  });
  result.push(group);
  return result;
}

function getLast(array) {
  return array[array.length - 1];
}

function copyObject(obj) {
  return JSON.parse(JSON.stringify(obj));
}

var statsGrouped = groupWith(stats, function(a, b) {return a.clr === b.clr});
for(var i = 1; i < statsGrouped.length; i++) {
  statsGrouped[i].unshift(copyObject(getLast(statsGrouped[i-1])));
  statsGrouped[i][0].clr = statsGrouped[i][1].clr;
}

console.log(statsGrouped);
Tesseract
  • 8,049
  • 2
  • 20
  • 37