am stuck now for the whole day and cannot get any further. I know, that I am missing a small thing, but just can't find it.
I got two arrays:
arrKeys = ["a", "b", "c"]
arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
I would like to get an array of objects, that looks like:
myObj = [
{
"a": 1,
"b": 2,
"c": 3
},
{
"a": 4,
"b": 5,
"c": 6
},
{
"a": 7,
"b": 8,
"c": 9
}
]
I tried to do something like:
const myObj = arrKeys.reduce((newObj, key, index) => {
if (arrValues[index] == undefined) arrValues[index] = null
newObj[key] = aarValues[index]
return newObj
}, {})
cosnole.log(myObj)
But the problem is, that arrKeys is looping only once and I do not know, how to "reset" the counter each time arrKeys gets to max length. Also I got only an object back, not an array of objects:
My result
myObj = {
"a": 1,
"b": 2,
"c": 3
}
Any ideas are really appreaciated.
You can iterate over the values, creating arrKeys.length chunks at a time, and then creating an object from the chunk by mapping the chunk index to the appropriate key. This approach has the advantage that if arrValues is not an exact multiple of arrKeys length, it will still work:
const f = (arrKeys, arrValues) => {
const result = []
const kLen = arrKeys.length
const vLen = arrValues.length
for (i = 0; i < vLen; i += kLen) {
chunk = arrValues.slice(i, i + kLen)
result.push(Object.fromEntries(chunk.map((v, i) => [arrKeys[i], v])))
}
return result;
}
console.log(f(["a", "b", "c"], [1, 2, 3, 4, 5, 6, 7, 8, 9]))
console.log(f(["a", "b", "c"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]))
console.log(f(["a", "b", "c", "d"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]))
You can use modulo operator to get check for every keys.length nth element and then add a new object by slicing the values array where the start is current index and end current index + keys.length
const f = (keys, values) => values.reduce((r, e, i) => {
if (i % keys.length === 0) {
const index = i / keys.length
r[index] = values.slice(i, i + keys.length).reduce((r, e, i) => {
r[keys[i]] = e
return r
}, {})
}
return r
}, [])
console.log(f(["a", "b", "c"], [1, 2, 3, 4, 5, 6, 7, 8, 9]))
console.log(f(["a", "b", "c", 'g'], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
console.log(f(["a", "b"], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]))
One way would be to loop through the arrValues using a conventional for...loop.
We can use the modulus operator % to determine where we are in the run of three.
Check the below for a demo:
var arrKeys = ["a", "b", "c"];
var arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9];
var myObj = [];
var newObj = null;
for(var i=0; i<arrValues.length; i++)
{
if(i % 3 === 0) // First run of three
newObj = {};
newObj[ arrKeys[i % 3] ] = arrValues[i];
if(i % 3 === 2) // We're at the end of the run of three
myObj.push(newObj);
}
console.log(myObj);
i do this with reduce
const arrKeys = ["a", "b", "c"]
const arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
let myObj = [];
arrValues.reduce((pre, cur,i) => {
pre[arrKeys[i % 3]] = cur;
if (i % 3 === 2) {
myObj.push(pre);
return {};
} else return pre;
}, {})
console.log(myObj)
you can do that...
const
arrKeys = ['a', 'b', 'c']
, arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
, myObj = arrValues.reduce((r,v,i) =>
{
if (!(i%3)) r.a.push(r.o = {})
r.o[arrKeys[i%3]] = v
return r
},{ o:null,a:[] }).a
;
console.log(myObj)
I think your desire to use Array#reduce was a good one, only I would use it:
To break the larger array into chunks of 3, then
To convert the chunks into objects
const arrKeys = ["a", "b", "c"],
arrValues = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
output = arrValues
.reduce(
(prev,cur,i,arr) =>
i % 3 === 0 ?
[
...prev,
arr.slice(i, i+3)
.reduce(
(ac,cu,j) =>
({...ac,[arrKeys[j]]:cu}), {}
)
] :
prev, []
);
console.log( output );
I'm creating a module that extends existing application. I've received a variable device and I want to create myDevice that will always hold the same data. Lets say that data is contained in an array:
https://jsfiddle.net/hmkg9q60/2/
var device = {
name: "one",
data: [1, 2, 3]
};
var myDevice = {
name: "two",
data: []
};
myDevice.data = device.data; // Assign array reference
device.data.push(4); // Push works on array reference
console.log(device.data); // [1, 2, 3, 4]
console.log(myDevice.data); // [1, 2, 3, 4] - ok
device.data = [0, 0, 0]; // A new array is assigned to 'device'
// and 'myDevice' reference stays with old array
console.log(device.data); // [0, 0, 0]
console.log(myDevice.data); // [1, 2, 3, 4] - I would like to get [0,0,0]
What I would like to obtain is to be sure, that myDevice will always hold the same data as device, even if someone decides to use the assign operator somewhere in the application. I don't want to clone myDevice because I want to hold "name" and other properties.
Is there a way in JavaScript to create such reference to an object field?
You could use getters and setters, and read and assign directly from and to the device object.
var device = {
name: "one",
data: [1, 2, 3]
};
var myDevice = {
name: "two",
get data() { return device.data; },
set data(newdata) { device.data = newdata; },
};
console.log(myDevice.data);
device.data = [4,5,6];
console.log(myDevice.data);
I would use a getter
NOTE: more elegant ES6 solution
var device = {
name: "one",
data: [1, 2, 3]
};
var myDevice = {}
myDevice.getData = () => device.data;
myDevice.bla = "bla";
device.data.push(4); // Push works on array reference
console.log(device.data); // [1, 2, 3, 4]
console.log(myDevice.getData()); // [1, 2, 3, 4] - ok
device.data = [0, 0, 0]; // A new array is assigned to 'device'
// and 'myDevice' reference stays with old array
console.log(device.data); // [0, 0, 0]
console.log(myDevice.getData()); // [1, 2, 3, 4] - I would like to get [0,0,0]
I have two jsons:
first: {
"a": 1,
"b": 9,
"c": 12,
"d": 5
}
and
second: {
"a": 7,
"e": 8,
"b": 11,
"f": 7
}
and i want to create chartjs bar that include both json (with two datasets).
The labels should be 'a', 'b', 'c', 'd', 'e', 'f' and the "first" dataset's data will be: 1, 9, 12, 5, 0, 0. The "second" dataset's data will be: 7, 11, 0, 0, 8, 7.
My code right now:
var barChartData = {
labels: Object.keys(first),
datasets:[
{
label:'first',
data: Object.values(first)
},
{
label: 'second',
data: Object.values(second)
}]
};
window.myBar = new Chart(document.getElementById("barChart").getContext("2d"),
{
type:'bar',
data: barChartData
});
The problem is that i want the labels to be from the keys of both 'first' and 'second' jsons and not just from the 'first' and also that the values will be suitable to the keys.
Is there any simple way to do this?
It looks like you want both objects to have the same keys but with a value of zero when the keys aren't defined. There are several ways to do this. One option would be to make a list of the combined keys of both objects and just loop over them setting the object's value to 0 if the key doesn't exist:
let first = {"a": 1,"b": 9,"c": 12,"d": 5 }
let second = {"a": 7,"e": 8,"b": 11,"f": 7}
Object.keys(Object.assign({}, first, second)) // get combined keys
.forEach(k => {
if (!first.hasOwnProperty(k)) first[k] = 0; // set 0 if key is not in object
if (!second.hasOwnProperty(k)) second[k] = 0;
})
console.log(first, second)
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));