1

I have an object that looks like this:

 obj={"a": [1,2],"b": [3,4],"c": [5,6]}

I need to create an array of objects where every object consists of each key with only one value corresponding to its order like this:

obj2=[{"a": 1, "b": 3, "c": 5},{"a": 2, "b": 4, "c": 6}]

Also, if I have a JSON string using JSON.stringify(obj), would it be somehow possible to create string corresponding to JSON.stringify(obj2) directly from the first one?

4
  • 2
    What's been tried? Commented Aug 13, 2018 at 14:00
  • 1
    It is not very clear how your initial object looks like. So, as your input you have an object with 3 (or possibly more) keys, named by alphabet lowercase letters (or not? can it be named other way?), and all of them (or not?) are actually arrays of the same (or not the same?) length. Commented Aug 13, 2018 at 14:01
  • @YeldarKurmangaliyev sorry i tried to picture as general as possible. The object may consist of various number of keys named arbitrarily but the arrays will be allways the same length. Commented Aug 13, 2018 at 14:09
  • @user3033054 see my edit for your second problem. Commented Aug 13, 2018 at 14:21

6 Answers 6

1

const obj = { "a": [1, 2], "b": [3, 4], "c": [5, 6] }
// create an array to store result
const result = []
// for each key in obj
Object.keys(obj).forEach(key => {
    // for each array element of the property obj[key]
    obj[key].forEach((value, index) => {
        // if an object doesn't exists at the current index in result
        // create it
        if (!result[index]) {
            result[index] = {}
        }
        // at the result index, set the key to the current value
        result[index][key] = value
    })
})
console.log(result)

Here is my algorithm, given the expected result .

Also, let's say i have a JSON string using JSON.stringify(obj), would it be somehow possible to create string corresponding to JSON.stringify(obj2) directly from the first one?

Yes, you could add .toJSON to obj:

const obj = { "a": [1, 2], "b": [3, 4], "c": [5, 6] }
Object.setPrototypeOf(obj, {
    toJSON: function () {
        const result = []
        Object.keys(this).forEach(key => {
            this[key].forEach((value, index) => {
                if (!result[index]) {
                    result[index] = {}
                }
                result[index][key] = value
            })
        })
        return JSON.stringify(result);
    }
})



console.log(JSON.stringify(obj))

You can use Object.setPrototypeOf so that toJSON method is not counted as an enumerable key when Object.keys(obj).forEach iterates

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON()_behavior

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

Comments

1

You can use Object.keys and Object.values to extract the keys and the values. Use Math.max to get the max length of the values. Use for to loop thru and use reduce to make new object.

var obj = {"a": [1, 2],"b": [3, 4],"c": [5, 6]};

var keys = Object.keys(obj);
var values = Object.values(obj);

var obj2 = [];

for (i = 0; i < Math.max(...values.map(o => o.length)); i++) {
  obj2.push(keys.reduce((c, v, k) => Object.assign(c, {[v]: values[k][i] || ""}), {}))
}

console.log(obj2);

This will work even if the given object values are not the same on length.

var obj = {
  "a": [1, 2],
  "b": [3, 4],
  "c": [5, 6, 10]
};

var keys = Object.keys(obj);
var values = Object.values(obj);

var obj2 = [];

for (i = 0; i < Math.max(...values.map(o => o.length)); i++) {
  obj2.push(keys.reduce((c, v, k) => Object.assign(c, {[v]: values[k][i] || ""}), {}))
}

console.log(obj2);

Comments

0

I believe this should do the trick:

obj={"a": [1,2],"b": [3,4],"c": [5,6]}
 
const transform = input => Object.values(input)[0]
  .map((_, i) => Object.keys(input)
    .reduce((prev, curr) => {
      prev[curr] = input[curr][i]
      return prev
    }, {}))
    
const result = transform(obj)

console.dir(result)

This will only work on objects where each value is an array of the same length. You take each index of the first value, then create an object for each key, getting the value using the aforementioned index.

Comments

0

If your values (arrays) have the same length.

obj = {"a": [1,2],"b": [3,4],"c": [5,6]};
obj2 = [];

var keys = Object.keys(obj)

for (i = 0; i < obj[keys[0]].length; i++) {
    temp = {};
    keys.forEach(x => temp[x] = obj[x][i]);
    obj2.push(temp);
}

console.log(obj2);

Comments

0

You could use a single loop for the keys and another for the value and map a new array.

This works for same length arrays.

var object = { a: [1, 2], b: [3, 4], c: [5, 6] },
    array = Object
        .entries(object)
        .reduce((r, [k, a]) => a.map((v, i) => Object.assign(r[i] || {}, { [k]: v })), []);
        
console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

0

You can iterate over the keys of the input object and construct the desired output with Array.prototype.reduce

var obj={"a": [1,2],"b": [3,4],"c": [5,6]};

var result = Object.keys(obj).reduce((a, k) => (obj[k].forEach((n, i) => a[i] = {...(a[i] || {}), ...{[k]: n}}), a),[]);
  
console.log(result);

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.