Merge two objects with different keys in chartjs bar - javascript

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)

Related

is there a javascript structure that allows to map multiple keys (non nested) to 1 single value

Example:
["a", "b"] -> 1
["c", "d", "e"] -> 2
I want to be able to give "d" as key and get 2.
This work with your example, but I am not sure it covers your real life case :D
const arrays = [['a','b'],['c','d','e']]
const struct = arrays.reduce((acc, array, index) => {
array.forEach(v => acc[v] = index + 1)
return acc
}, {})
console.log(struct)
console.log(struct.d)
output
{a: 1, b: 1, c: 2, d: 2, e: 2}
2
You could just use an object like this:
{
"a": 1,
"b": 1,
"c": 2,
"d": 2,
"e": 2,
}
but this has the problem of if you wanted to change all 1s to 3, you'd have to change it in each place.
You can do this:
const data = [1, 2];
const map = {
"a": data[0],
"b": data[0],
"c": data[1],
"d": data[1],
"e": data[1],
}
so that you only have to set the result in one place.
you can also do stuff with Sets or nested arrays, but that prevents the lookup from being O(1) and changes it to O(n) or O(n*m) based on implementation.
Not sure if exactly what you are looking for but you can do it with built-in object and array methods.
Object.fromEntries(
Object.entries(["c", "d", "e"]).map((a) => {
a.reverse();
a[1] = Number(a[1]);
return a;
})
);
This will output:
{ c: 0, d: 1, e: 2 }
But I see you want to start from 1 and not 0, in that case you could map bit more:
Object.fromEntries(
Object.entries(["c", "d", "e"]).map((a) => {
a.reverse();
a[1] = Number(a[1]) + 1;
return a;
})
);
Then you get
{ c: 1, d: 2, e: 3 }

js-xlsx - get particular rows of excel sheet

I have an Excel sheet which has 500 rows. I am trying to get the rows from 101 to 200.
I have searched in google, and I have found an example to get starting rows, e.g. 1 to 100 or 1 to 1000, or even 1 to any number.
But I haven't found any code to get rows from mth row to nth row (Here 'm' and 'n' can be any number eg m=101 to n=200)
Below is the code which I have found to get first 100 rows:
let workbook = XLSX.readFile('./files/uploaded_files/testfile.xlsx', {sheetRows: 100})
const wsname = workbook.SheetNames[0];
const ws = workbook.Sheets[wsname];
var exceldata = XLSX.utils.sheet_to_json(ws);
Even if there is any other module to get the rows in between, I would like to know if there is any ?
Using a smaller example of:
There are several options:
You can use your current approach and slice the array returned from sheet_to_json e.g.
// option 1
const maxRow = 6;
const minRow = 3;
const wb = XLSX.readFile("./Book1.xlsx", {sheetRows: maxRow});
const ws = wb.Sheets[wb.SheetNames[0]];
let data = XLSX.utils.sheet_to_json(ws);
data = data.slice(minRow <= 2 ? 0 : minRow - 2);
console.log(data);
It's minRow - 2 to account for 1 row being headers and that the other 1 is to include row 3, not exclude it. This produces:
[
{ a: 4, b: 5, c: 6 },
{ a: 7, b: 8, c: 9 },
{ a: 10, b: 11, c: 12 },
{ a: 13, b: 14, c: 15 }
]
Another option is to combine use of the range and header (see here) options. range allows you to control what range is considered by sheet_to_json and header is used to define the keys used in the output array of objects.
You can use this after importing the whole file or continue to use the sheetRows option as well e.g.:
// option 2
const importRange = "A3:F6";
const headers = ["a", "b", "c"];
const wb = XLSX.readFile("./Book1.xlsx"); // not using sheetRows
const ws = wb.Sheets[wb.SheetNames[0]];
const data = XLSX.utils.sheet_to_json(ws, {range: importRange, header: headers});
console.log(data);
Which produces:
[
{ a: 4, b: 5, c: 6 },
{ a: 7, b: 8, c: 9 },
{ a: 10, b: 11, c: 12 },
{ a: 13, b: 14, c: 15 }
]
Noting that if you omit the headers option then the output is:
[
{ '4': 7, '5': 8, '6': 9 },
{ '4': 10, '5': 11, '6': 12 },
{ '4': 13, '5': 14, '6': 15 }
]
Because the values in row 3 become the new default headers (which I think you probably don't want).
Finally, if you don't know the headers in advance you can just get an array of arrays and figure the headers out later:
// option 3
const importRange = "A3:F6";
const headers = 1;
const wb = XLSX.readFile("./Book1.xlsx"); // not using sheetRows
const ws = wb.Sheets[wb.SheetNames[0]];
const data = XLSX.utils.sheet_to_json(ws, {range: importRange, header: headers});
console.log(data);
Which produces:
[
[ 4, 5, 6 ],
[ 7, 8, 9 ],
[ 10, 11, 12 ],
[ 13, 14, 15 ]
]

How to Change CSV Objects to JSON in NodeJS

I am trying to change csv file output to array of objects, i am using node-xlsx library to get values of the csv file and i am trying to change it to array of Json object
Example csv file
var csvData = [
["a", "b", "c", "d"],
[1, 2, 3, 4]
[5, 6, 7, 8]
];
JSON file
var data = [
{
a: 1,
b: 2,
c: 3,
d: 4,
},
{
a: 5,
b: 6,
c: 7,
d: 8,
},
];
It's not a matter of json or csv, you just need to move the data from the first array to a key-value data type.
I would use a loop such as this:
data=[];
for(var i=1; i<csvData.length; i++) {
var obj={};
for(var j=0; j<csvData[0].length; j++) {
obj[csvData[0][j]]=csvData[i][j];
}
data.push(obj);
}
Then you can use JSON.stingify(data) to convert it into a JSON string

Merge 2 object with same key, value from 2 array

I want to merge 2 object with same key, value from 2 array, something like this:
var arr1 = [
{ a: "a", 1: 1, 2: 2 },
{ a: "b", 1: 1, 2: 3 }
];
var arr2 = [
{ a: "a", 3: 123 },
{ a: "b", 3: 4411 }
];
var arr3 = _.map(arr1, function(a1) {
var a3 = {};
_.map(arr2, function(a2) {
if (a1.a == a2.a) {
a3 = _.extend(a1, a2);
}
})
return a3
});
result:
arr3 = [
{ '1': 1, '2': 2, '3': 123, a: 'a' },
{ '1': 1, '2': 3, '3': 4411, a: 'b' }
]
Does it look stupid? Are there any others ways to do this?
Thanks for reading.
Use a lodash chain to concat the arrays, group similar objects, and then merge each group to a single object:
var arr1 = [{ a: "a", 1: 1, 2: 2 }, { a: "b", 1: 1, 2: 3 }];
var arr2 = [{ a: "a", 3: 123 }, { a: "b", 3: 4411 }];
var result = _(arr1)
.concat(arr2) // concat the 2nd array
.groupBy('a') // group by the identical key
.map(_.spread(_.curry(_.merge, {}))) // left currey merge to to create a new empty object, and spread the group as parameters
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
With ES6 you can use Array#reduce to collect the similar objects in a Map, then get the Map#values iterator, and use the spread syntax to convert to an array:
const arr1 = [{ a: "a", 1: 1, 2: 2 }, { a: "b", 1: 1, 2: 3 }];
const arr2 = [{ a: "a", 3: 123 }, { a: "b", 3: 4411 }];
const result = [...arr1.concat(arr2) // concat the arrays
.reduce((m, o) => m.set(o.a, Object.assign(m.get(o.a) || {}, o)), // use a map to collect similar objects
new Map()
).values()]; // get the values iterator of the map, and spread into a new array
console.log(result);
you can do
var arr1 = [
{ a: "a", 1: 1, 2: 2 },
{ a: "b", 1: 1, 2: 3 }
];
var arr2 = [
{ a: "a", 3: 123 },
{ a: "b", 3: 4411 }
];
let result = arr1.map((e) => {
for(let element of arr2){
if(e.a == element.a) Object.assign(e, element);
}
return e;
});
console.log(result);

Searching key/value pair from one object to another in JavaScript

If I have an array of objects and one object in JavaScript:
var data = [{"a": 1, "b": 2}, {"a": 1}, {"a": 1, "b": 2, "c": 3}];
var myFilter = {"a": 1, "b": 2};
...and would like to use myFilter object as a filter to the array of objects to create a new array of objects if and only if the object at least matches or contain the myFilter key/value pairs.
Any recommendation how can I go ahead and put it into code? I need to create a new array that was filtered from data using the myFilter key/value pair.
I was able to do this but myFilter only contains 1 key/value pair.
My expected new array is:
var newArr = [];
newArr = [{"a": 1, "b": 2}, {"a": 1, "b": 2, "c": 3}];
You can use arr.filter(callback[, thisArg]) for this:
var data = [{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 3 }]
var myFilter = { "a": 1, "b": 2 }
var myFilterFunction = function(obj) {
for (var p in myFilter) {
if (obj[p] !== myFilter[p]) return false
}
return true
}
var newArr = data.filter(myFilterFunction)
document.write(JSON.stringify(newArr))
A more universal approach would be this filterFuncByObj(filterObj) function, wich takes any custom filter object:
data.filter(filterFuncByObj(myFilter)):
var data = [{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 3 }]
var myFilter = { "a": 1, "b": 2 }
var newArr = data.filter(filterFuncByObj(myFilter))
// Demo Output
document.write(JSON.stringify(newArr))
function filterFuncByObj(filterObj) {
return function(obj) {
for (var p in filterObj) {
if (obj[p] !== filterObj[p]) return false
}
return true
}
}
Using Array.filter(), Object.keys() and Array.every() this could be one way to go
var data = [{"a": 1, "b": 2}, {"a": 1}, {"a": 1, "b": 2, "c": 3}];
var myFilter = {"a": 1, "b": 2};
var filteredData = data.filter(function(d) {
return Object.keys(myFilter).every(function(f) {
return d[f] === myFilter[f];
})
});
console.log(JSON.stringify(filteredData));
The lodash way, just in case:
var data = [{ "a": 1, "b": 2 }, { "a": 1 }, { "a": 1, "b": 2, "c": 3 }];
var myFilter = { "a": 1, "b": 2 };
var newArr = _.filter(data, myFilter);
document.write(JSON.stringify(newArr, null, 3));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>

Categories

Resources