2

I have one object that I had to take apart into two arrays to handle properly. It looked like this:

{
  city:"stuttgart",
  street:"randomstreet",
  ...
}

Since it needs to fit a certain directive I had to convert it to:

[
  {key:"city", value:"stuttgart"}
  {key:"street", value:"randomstreet"},
  ...
]

for this I first used

var mapFromObjectWithIndex = function (array) {
  return $.map(array, function(value, index) {
    return [value];
  });
};

var mapFromObjectWithValue = function (array) {
  return $.map(array, function(value, index) {
    return [index];
  });
});

to create two arrays, one containing the old key, the other one is holding the old value. Then I created another, two dimensional array map them into a single array doing this

var mapToArray = function (arrayValue, arrayIndex) {
  var tableData = [];
  for (var i = 0; i<arrayIndex.length; i++){
    tableData[i] = {key:arrayIndex[i] , value:arrayValue[i]};
  }
  return tableData;
};

(maybe I have already messed up by here, can this be done any easier?)

Now, I use the array (tableData) to display the data in a form. The value fields can be edited. In the end, I want to convert the array (tableData) to its original. (see first object)

Please note, that the original object doesn't only contain strings as values, but can also contain objects as well.

1
  • Just a side note: kyes in objects are not guaranteed to maintain the initial order. So, after converting your object to an array your data may be in random order. Commented Aug 9, 2016 at 15:04

4 Answers 4

12

I think conversion can be definitely easier:

var obj = {
  city:"stuttgart",
  street:"randomstreet",
};

var tableData = Object.keys(obj).map(k => {return {key: k, value: obj[k]}});

console.log(tableData);

var dataBack = {};
tableData.forEach(o => dataBack[o.key] = o.value);

console.log(dataBack);

What do you want to do with objects? Do you want to expand them as well? If yes you can do something like this (and it works with nested objects as well):

var obj = {
  city:"stuttgart",
  street:"randomstreet",
  obj: {a: 'a', b: 'b'},
  subObject: {aha: {z: 'z', y: 'y'}}
};

function trasformToTableData(obj) {
  if (typeof obj !== 'object') return obj;
  return Object.keys(obj).map(k => {return {key: k, value: trasformToTableData(obj[k])}});
}

var tableData = trasformToTableData(obj);
console.log(tableData);

function transformBack(obj) {
  if (Array.isArray(obj)) {
    var support ={};
    for (let i = 0; i < obj.length; i++) {
      support[obj[i].key] = transformBack(obj[i].value)
    }
    return support;
  }
  return obj;
}

var dataBack = {};
tableData.forEach(o => dataBack[o.key] = transformBack(o.value));

console.log(dataBack);

Sign up to request clarification or add additional context in comments.

2 Comments

I think your answer suits me best and is the most complete and flexible. Also thanks for simplifying the whole process extremely. Also the first time I see arrow notation (which, at least Webstorm didn't like, so I rewrote)
@MichaelGerullis glad it helped! Arrows functions are a quite powerful tool of ES6 - not in this example, but they do automatically set the binding of this keyword. Of course they can be changed in normal inline functions
3

Let's have some fun and turn our object into iterable to do the job as follows;

var input = {city:"stuttgart", street:"randomstreet", number: "42"};
   output = [];
input[Symbol.iterator] = function*(){
                           var ok = Object.keys(this),
                                i = 0;
                           while (i < ok.length) yield {key : ok[i], value: this[ok[i++]]};
                         };
output = [...input];
console.log(output);

3 Comments

Can you explain how your answer works? Also, the output doesn't seem to be in the correct form.
@Cristy Thank you i have corrected the output to show as required. In this snippet i am making an object iterable by assigning it a Symbol.iterator method. This makes iterators such as the for of loop or the spread operator to be able to iterate this object (by invoking the iterator method they get returned an iterator object and keep calling it's next method - AKA generators iterators) They get returned whatever we yield in the Symbol.iterator function (generator function) So that's how it is. :)
i just came back to this after quite some years. Fun code. Yeah. Definitely fun but at the time i had no idea what a generator was.
2

This function will map your object to an array when you call objVar.mapToArray(), by using Object.keys() and .map()

Object.prototype.mapToArray = function() {
  return Object.keys(this).map(function(v) {
    return { key: v, value: this[v] };
  }.bind(this));
}

1 Comment

1st: map() has a second argument, you don't need to bind, 2nd: if you use a fat arrow you don't even need this second argument, and 3rd: Guys, stop extending some native prototypes for every puny little utility you write. Especially don't extend Object's prototype, why? because "wtf".mapToArray() or window.addEventListener.mapToArray() everything inherits it. keep it simple: var mapToArray = obj => Object.keys(obj).map(k => ({ key: k, value: obj[k] }))
1

I would do something like this:

var dataObj = {
  city:"stuttgart",
  street:"randomstreet",
};

function toKeyValue(obj) {
  var arr = [];
  for (var key in obj) {
    if(obj.hasOwnProperty(key)) {
      arr.push({'key': key, 'value': obj[key]});
    }
  }
  return arr;
}

var arrayKeyValue = toKeyValue(dataObj);
console.log(arrayKeyValue);

Comments

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.