-1

This is an object that I have.

var MyObject  =  {
    'stop1-start': "0", 
    'stop1-color': "#0074a2", 
    'stop2-start': "32", 
    'stop2-color': "#ff6600"
};

this is an array that I need.

var newArray =[
    {
        'stop-start': "0",
        'stop-color': "#0074a2",
    },
    {
        'stop-start': "32",
        'stop-color': "#ff6600",
    }
];

I tried for loops, jquery each but just cant wrap my head around it.

Any help is appreciated.

3 Answers 3

3

You should figure out which numbers are present first, for safety's sake, then turn each pair into a record. Like so:

var MyObject = {
  'stop1-start': "0",
  'stop1-color': "#0074a2",
  'stop2-start': "32",
  'stop2-color': "#ff6600"
};

function createArray(data) {
  // Figure out which numbers are present
  var numbers = Object.keys(data).map(function(key) {
    return parseInt(key.match(/stop(\d+)/)[1], 10);
  });

  // Filter out duplicates
  numbers = numbers.filter(function (num, idx, arr) {
    // Only take the first instance of each value
    return arr.indexOf(num) === idx; 
  }).sort();

  // For each number, create a record
  var records = numbers.map(function(num) {
    var start = 'stop' + num + '-start';
    var color = 'stop' + num + '-color';
    return {
      start: data[start],
      color: data[color]
    };
  });
  
  return records;
}

document.getElementById('r').textContent = JSON.stringify(createArray(MyObject));
<pre id=r></pre>

If you want to get all clever and functional, you can turn the whole algorithm into a single chain:

function createArray(data) {
  // Figure out which numbers are present
  return Object.keys(data).map(function(key) {
    return parseInt(key.match(/stop(\d+)/)[1], 10);
  }).filter(function (num, idx, arr) {
    // Only take the first instance of each value
    return arr.indexOf(num) === idx; 
  }).sort().map(function(num) {
    var start = 'stop' + num + '-start';
    var color = 'stop' + num + '-color';
    return {
      start: data[start],
      color: data[color]
    };
  });
}

If you have access to ES6, you can use that for some shorthand:

function createArray(data) {
  return Object.keys(data)
    .map(key =>  parseInt(key.match(/stop(\d+)/)[1], 10))
    .filter((num, idx, arr) => arr.indexOf(num) === idx)
    .sort()
    .map(num => {
      return {
        start: data[`stop${num}-start`],
        color: data[`stop${num}-color`]
      };
    });
}
Sign up to request clarification or add additional context in comments.

4 Comments

Almost perfect! Good idea checking which numbers are present in the first place.
yes, they were duplicates in , this one works fine now. great function!
Yeah, just fixed an issue where I wasn't filtering out dupes. This should work correctly now.
Added a sort clause to make sure the keys are in order. This won't retain gaps (if you have [1, 2, 9] it will output [1, 2, 3]) but will retain order.
1

Object keys are not guaranteed to be in order, so you'll need to find the array's index within the key itself:

var MyObject  =  {
  'stop1-start': "0", 
  'stop1-color': "#0074a2", 
  'stop2-start': "32", 
  'stop2-color': "#ff6600"
};

var newArray= [];

Object.keys(MyObject).sort().forEach(function(key) {
  var num= key.match(/(\d+)/)[0] - 1;
  newArray[num] = newArray[num] || {};
  newArray[num][key.replace(num+1,'')]= MyObject[key];
});

document.body.innerHTML= JSON.stringify(newArray);

8 Comments

excellent and the exact way I was hoping for. this way I dont have to match the key strings in case they are different.
Assigning to array elements like that will create a sparse array and confuse a lot of people. Why are you using the regex multiple times when you can just save the matches (since you already have the index)? What does obj do?
Good points, @ssube. The obj was left over from an earlier attempt – now removed. I also removed the additional regex.
What advantage does the sparse array provide? Generally, avoiding those is a good thing, since most JS naively assumes that arrays will be contiguous. Sorting the keys should have all the same benefits (retaining order) but compact them along the way (to be fair, I entirely forgot to sort in my original answer).
@RickHitchcock forEach is supported even less
|
1

Try:

var newArray = [], current = {}, i = 0;

for(var key in MyObject){
    current[i % 2 ? "stop-color" : "stop-start"] = MyObject[key];
    i++ % 2 && (newArray.push(current), current = {})
}

Demo

1 Comment

This may not work in some since browsers, because an object's keys aren't guaranteed to be returned in order using in.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.