const myObj = {
a: [1, 2, 3],
b: [2, 4, 6],
c: [10, 20, 30]
}
Into
const myCollection = [
{a: 1, b: 2, c: 10},
{a: 2, b: 4, c: 20},
{a: 3, b: 6, c: 30}
]
I tried combinations of Object.entries, Object.keys and map but I'm always finding myself iterating twice or more over myObj and I'm not happy with any solution I came up with.
So what is the most efficient (in terms of time complexity) and elegant way that you can think to achieve that?
Just in case you'd need variable length:
const myObj = {
a: [1, 2, 3],
b: [2, 4, 6,8, 10],
c: [10, 20, 30, 40],
};
let myCollection = [];
Object.keys(myObj).forEach((k) => {
for (let i = 0; i < myObj[k].length; i++) {
if (!myCollection[i]) myCollection.push({});
myCollection[i][k] = myObj[k][i];
}
});
console.log(myCollection);
You could reduce the entries and map nested arrays.
const
object = { a: [1, 2, 3], b: [2, 4, 6], c: [10, 20, 30] },
result = Object
.entries(object)
.reduce((r, [k, a]) => a.map((v, i) => ({ ...r[i], [k]: v })), []);
console.log(result);
That can be done using Array.reduce. I have attached the conversion code.
const myObj = {
a: [1, 2, 3],
b: [2, 4, 6],
c: [10, 20, 30]
}
const myCollection = [
{a: 1, b: 2, c: 10},
{a: 2, b: 4, c: 20},
{a: 3, b: 6, c: 30}
]
const maxLength = Math.max(...Object.values(myObj).map(item => item.length));
const myObjKeys = Object.keys(myObj);
const result = [ ...Array(maxLength).keys() ].map((index) => {
return myObjKeys.reduce((acc, curKey) => {
if (myObj[curKey].length > index) {
acc[curKey] = myObj[curKey][index];
}
return acc;
}, {});
});
console.log(result);
Using ramdajs, I could suggest you a short way like below
const myObj = {
a: [1, 2, 3],
b: [2, 4, 6],
c: [10, 20, 30]
}
const res = R.map(
R.zipObj(R.keys(myObj)),
R.values(myObj)
)
console.log(res)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
In ramdajs homepage, criteria 3 in What's Different, it cited that
The parameters to Ramda functions are arranged to make it convenient for currying. The data to be operated on is generally supplied last.
You can use map() on Object.values and then use reduce() on each value.
const myObj = {
a: [1, 2, 3],
b: [2, 4, 6],
c: [10, 20, 30]
}
let keys = Object.keys(myObj);
const arr = Object.values(myObj).map((a) => a.reduce((ac, a, i) => ({...ac, [keys[i]]:a}), {}));
console.log(arr)
Related
Suppose I have:
const KEYS = ['b', 'a', 'c']
const obj = {
2018: {a: 1, b: 2, c: 3},
2019: {a: 4, b: 5, c: 6},
2020: {a: 7, b: 8, c: 9},
}
This is what I would like to get:
const result = {
2018: {
a: [0, 1, 0],
b: [2, 0, 0],
c: [0, 0, 3]
},
2019: {
a: [0, 4, 0],
b: [5, 0, 0],
c: [0, 0, 6]
},,
2020: {
a: [0, 7, 0],
b: [8, 0, 0],
c: [0, 0, 9]
},
}
result['2018'] object has three keys. Each key value is an array that contains the values in the order that is set by KEYS using 0 as fill value.
How can I do something like this?
This is what I tried but obviously is more complicated than this:
const reshaped = Object.entries(obj).map(([key, value]) => {
return { [key]: Object.values(value) }
})
// [
// { 2018: [ 1, 2, 3 ] },
// { 2019: [ 4, 5, 6 ] },
// { 2020: [ 7, 8, 9 ] }
// ]
You could map the wanted keys in order abd build an array for each property.
const
KEYS = ['b', 'a', 'c'],
object = { 2018: { a: 1, b: 2, c: 3 }, 2019: { a: 4, b: 5, c: 6 }, 2020: { a: 7, b: 8, c: 9 } },
result = Object.fromEntries(Object.entries(object).map(([k, o]) => [
k,
Object.fromEntries(Object.entries(o).map(([l, v]) => [
l,
KEYS.map(m => l === m ? v : 0)
]))
]));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You could use a combination of Object.entries and Object.fromEntries to map the object and then just create a new array with the length of the KEYS arr.
const KEYS = ['b', 'a', 'c']
const obj = {
2018: {a: 1, b: 2, c: 3},
2019: {a: 4, b: 5, c: 6},
2020: {a: 7, b: 8, c: 9},
}
const result = Object.fromEntries( // Create obj from array of entries
Object.entries(obj).map(([key, value]) => [ // create array of entries from obj and map it
key,
Object.fromEntries( // do the same obj/arr transformation on the value
Object.entries(value).map(([subKey, subValue]) => {
const arr = new Array(KEYS.length).fill(0); // create new array of keys length and fill all zeroes
arr[KEYS.indexOf(subKey)] = subValue; // on the index of the key in the KEYS arr, set the value of the key
return [subKey, arr]; // return subValue
})
)
])
);
console.log(result);
I have an object with number values assigned to keys
obj1 = {a : 10
b : 5
c : 6 }
and I want to decrement each number to zero so that each key has all values in that range, i.e:
obj2 = {a : 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
b : 5, 4, 3, 2, 1, 0
c : 6, 5, 4, 3, 2, 1, 0}
ive tried .map, .apply, and several other attempts at iteration. how can I accomplish this?
You can create an array of object entries, and then use reduce() to create the result object:
const obj1 = {
a: 10,
b: 5,
c: 6
};
const obj2 = Object.entries(obj1).reduce((a, [k, v]) => ({
...a,
[k]: Array(v + 1).fill(0).map(_ => v--)
}), {});
console.log(obj2);
Here is a much simpler solution:
const obj1 = { a: 5, b: 6, c: 3 };
let obj2;
Object.keys(obj1)
.forEach((key) => {
const size = obj1[key];
obj2[key] = new Array(size + 1)
.fill(0)
.map((val, index) => size - index);
});
console.log(obj2);
The result thus obtained will be in this format:
{
a: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
b: [5, 4, 3, 2, 1, 0],
c: [6, 5, 4, 3, 2, 1, 0],
}
let obj1 = {
a: 10,
b: 5,
c: 6,
};
let obj2 = Object.fromEntries(Object.entries(obj1).map(([k, v]) => [k, [...Array(v)].map((_, i) => v - i)]));
console.log(obj2);
let obj1 = {a : 10, b : 5, c : 6}
let res = Object.entries(obj1).reduce((acc, cur) => {
return Object.assign(acc, {[cur[0]]: Array.from(Array(cur[1]+1).keys()).reverse().join()})
}, {})
console.log(res)
I want to convert the following array:
const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]];
to the following object:
const data = [
{
a: 1,
b: 2,
c: 3,
d: 4
},
{
a: 5,
b: 6,
c: 7,
d: 8
},
{
a: 9,
b: 10,
c: 11,
d: 12
}
];
How do I do it using loop or some other way, of course?
This is a basic map / reduce operation where you map the outer array to a new one where each value (array) is reduced to a single object.
Given the simple nature of each value (a single array with four values), you can skip Array.prototype.reduce() for some array destructuring.
For example
const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]];
const newData = data.map(([ a, b, c, d ]) => ({ a, b, c, d }))
console.info(newData)
Note that this really hinges on knowing the data structure and no surprises (more or fewer elements in each array for example).
If you wanted a much more robust version, you'll want something like this
const data = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10, 11, 12]];
const newData = data.map(arr => arr.reduce((obj, val, idx) => ({
...obj,
[String.fromCharCode(97 + idx)]: val
}), Object.create(null)))
console.info(newData)
The only thing to worry about here is if your arrays contain more than 26 elements. Then your object keys are going to get weird.
You can use Array.prototype.map() combined with Array.prototype.reduce()
Code:
const alphabet = [...'abcdefghijklmnopqrstuvwxyz'];
const data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]];
const reasult = data.map(arr => arr.reduce((a, c, i) => (a[alphabet[i]] = c, a), {}));
console.log(reasult);
var temparray1 = [[1,3,4],[5,6,7],[8,9,10]];
var final = [];
var obj = {};
for(var temp in temparray1){
for(var test in temparray1[temp]){
obj.b = temparray1[temp][0];
obj.c = temparray1[temp][1];
obj.d = temparray1[temp][2];
}
console.log(obj);
final.push(obj);
}
current output
[{ b: 8, c: 9, d: 10 }
{ b: 8, c: 9, d: 10 }
{ b: 8, c: 9, d: 10 }]
expected Out put:
[{ b: 1, c: 3, d: 4 }
{ b: 5, c: 6, d: 7 }
{ b: 8, c: 9, d: 10 }]
i am running my javascript in node.js -v 8.1.x server
in the console at the end of the for loop it prints the required out put but not in the array push
var temparray = [[1, 3, 4], [5, 6, 7], [8, 9, 10]];
const final = temparray.map(a => ({ b: a[0], c: a[1], d: a[2] }));
console.log(final);
Probably, you set obj outside the for loop, therefore the props are overwritten and you push the same object multiple times into the array. Simply move the obj declaration into the loop. And you probably just need the outer loop.
Btw much shorter:
let final = temparray1.map(
([b,c,d]) => ({b,c,d})
);
You could use Array#map and return an object with the wanted properties.
var array = [[1, 3, 4], [5, 6, 7], [8, 9, 10]],
result = array.map(function (a) {
return { b: a[0], c: a[1], d: a[2] };
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With ES6, you could map the inner arrays as well with an array for the keys with Object.assign and spread syntax ....
var array = [[1, 3, 4], [5, 6, 7], [8, 9, 10]],
keys = ['b', 'c', 'd'],
result = array.map(a => Object.assign(...keys.map((k, i) => ({ [k]: a[i] }))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here is what you wanted
var temparray1 = [[1,3,4],[5,6,7],[8,9,10]];
var final = [];
for(var temp in temparray1){
var obj = {};
obj['b'] = temparray1[temp][0];
obj['c'] = temparray1[temp][1];
obj['d'] = temparray1[temp][2];
final.push(obj);
}
console.log(final);
Hope this helps!
I have an object like this:
var myObj = {
a: 1,
b: 2,
c: 3,
d: 4
};
And i want to convert that object to a multi-dimensional array like this:
var myArray = [['a', 1], ['b', 2], ['c', 3], ['d', 4]];
How could i achieve this?
You can use Object.entries function.
var myObj = { a: 1, b: 2, c: 3, d: 4 },
myArray = Object.entries(myObj);
console.log(JSON.stringify(myArray));
...or Object.keys and Array#map functions.
var myObj = { a: 1, b: 2, c: 3, d: 4 },
myArray = Object.keys(myObj).map(v => new Array(v, myObj[v]));
console.log(JSON.stringify(myArray));
var myArray = [];
var myObj = { a: 1, b: 2, c: 3, d: 4 };
for(var key in myObj) {
myArray.push([key, myObj[key]]);
}
console.log(JSON.stringify(myArray));