I'm trying to use data-forge to join two dataframes, but I'm getting an empty merged dataframe:
const a = new DataFrame([{ A: 10, b: 1 }, { A: 20, b: 2 }, { A: 30, b: 3 }]);
const b = new DataFrame([{ A: 10, c:11 }, { A: 20, c:22 }, { A: 30, c:33 }]);
const ab = a.join(
b,
left => left.A,
right => right.A,
(left, right) => {
return { A: left.A, b: left.b, c: right.c };
}
);
// {content: null}
I believe your join is working as intended. I suspect the reason your are getting {content: null} is that your are console.logging ab, but due to data-forge's lazy evaluation, it hasn't resolved the content. If you use the .toString() method, it forces lazy evaluation to complete. Try this:
const a = new dataForge.DataFrame([
{ A: 10, b: 1 },
{ A: 20, b: 2 },
{ A: 30, b: 3 },
]);
const b = new dataForge.DataFrame([
{ A: 10, c: 11 },
{ A: 20, c: 22 },
{ A: 30, c: 33 },
]);
const ab = a.join(
b,
(left) => left.A,
(right) => right.A,
(left, right) => {
return { A: left.A, b: left.b, c: right.c };
},
);
console.log(ab);
// DataFrame { configFn: [Function], content: null }
console.log(ab.toString());
// __index__ A b c
// --------- -- - --
// 0 10 1 11
// 1 20 2 22
// 2 30 3 33
Related
I'm a beginner in javaScript, I have this object MyGraph:
const MyGraph = {
a: { b: 5, c: 2 },
b: { a: 5, c: 7, d: 8 },
c: { a: 2, b: 7, d: 4, e: 8 },
};
I want to delete property "a" and its values in other properties as well to get this result:
const MyGraph = {
b: { c: 7, d: 8 },
c: { b: 7, d: 4, e: 8 },
};
I tried like this:
for(let XXX of Object.keys(MyGraph)){
console.log(XXX.a);
delete XXX.a;
}
the result of execution:
undefined
undefined
undefined
any help!
You could use a recursive algorithm :
function del_entries(key, obj) {
if (obj.hasOwnProperty(key)) {
delete obj[key];
}
// Or with Object.hasOwn, not fully supported by old browsers but more up to date
/*
if (Object.hasOwn(obj, key)) {
delete obj[key]
}
*/
Object.values(obj).forEach(o=> del_entries(key, o))
}
const MyGraph = {
a: { b: 5, c: 2 },
b: { a: 5, c: 7, d: 8 },
c: { a: 2, b: 7, d: 4, e: 8 },
};
del_entries("a", MyGraph);
console.log(MyGraph)
In your code XXX is the key. You need to do graph[XXX] to access the actual object. So instead of XXX.a you should do graph[XXX].a. But this only accounts for objects in graph that have an the key a. You also need to account for key a in graph. Please see the code below. Its a rudimentary example.
If you have one level of nesting then you can use then you can use the code below.
const mygraph = {
a: { b: 5, c: 2 },
b: { a: 5, c: 7, d: 8 },
c: { a: 2, b: 7, d: 4, e: 8 },
};
console.log(mygraph);
function deletePropAndValuesOf(key, graph) {
for (const k of Object.keys(graph)) {
if (k === key) {
delete graph[key];
} else {
if (key in graph[k]) {
delete graph[k][key]
}
}
}
}
deletePropAndValuesOf("a", graph);
console.log(mygraph);
You can copy the code to a .js file and run it using node. e.g.
Ive used object destructuring to remove the first array with an a, but could not figure out how to do all the a's's but the code below might help?
const MyGraph = {
a: { b: 5, c: 2 },
b: { a: 5, c: 7, d: 8 },
c: { a: 2, b: 7, d: 4, e: 8 }};
const {a, ...newMyGraph} = MyGraph;
// output
console.log(newMyGraph)
returns
b: {
a: 5,
c: 7,
d: 8
},
c: {
a: 2,
b: 7,
d: 4,
e: 8
}
}
I have a sample Array of objects like this
let items = [
{
a: '',
b: 2,
c: 3
},
{
a: '',
b: '',
c: 5,
d: 10
},
{
a: '',
b: '',
c: 6,
}
]
I want to find the first object that has the highest number of keys.
Clearly from the above, the second object has the highest number of keys.
How can I achieve this?
Thank you.
Something like this will work:
let highestLength = 0;
let highestItem = 0;
for (let i = 0; i < items.length; i++) {
let objLength = Object.keys(items[i]).length;
if (objLength > highestLength) {
highestLength = objLength;
highestItem = i;
}
}
Then highestItem will hold the index of the first element with the highest number of keys.
Start by .sort()ing in descending order by number of keys. Then return the first element.
let items = [{
a: '',
b: 2,
c: 3
},
{
a: '',
b: '',
c: 5,
d: 10
},
{
a: '',
b: '',
c: 6,
}
];
const mostkeys = items.sort(
(a,b) => Object.keys(b).length - Object.keys(a).length
)[0];
console.log( mostkeys );
If, however, you have more than one having the most keys and you would like to return all, your approach would be slightly different at the last step:
let items = [{
a: '',
b: 2,
c: 3
},
{
a: '',
b: '',
c: 5,
d: 10
},
{
a: '',
b: '',
c: 6,
},
{
c: '',
d: '',
e: 6,
f: 3
}
];
const mostkeys = items.sort(
(a,b) => Object.keys(b).length - Object.keys(a).length
)
.reduce((m, cur, i, a) =>
i === 0 ? [...m,cur] : Object.keys(cur).length < Object.keys(m[0]).length ? m : [...m,cur], []
);
console.log( mostkeys );
Say I have an array of objects like this:
const arr = [
{ a: 1, b: 2, c: 3, d: 4 },
{ a: 1 },
{ a: 1, b: 2, c: 3 },
{ a: 1, b: 2 }
];
How can I return the object with the most properties/keys? Preferably using in an efficient and terse manner using higher order functions.
You could assign to a single object.
const
array = [{ a: 1, b: 2, c: 3, d: 4 }, { a: 1 }, { a: 1, b: 2, c: 3 }, { a: 1, b: 2 }],
object = Object.assign({}, ...array);
console.log(object);
If you have different values, you could reduce the array.
const
array = [{ a: 1, b: 2, c: 3, d: 4 }, { a: 1 }, { a: 1, b: 2, c: 3 }, { a: 1, b: 2 }],
object = array.reduce((a, b) => Object.keys(a).length > Object.keys(b).length
? a
: b
);
console.log(object);
You can get the number of keys from an object by calling Object.keys(obj) and then checking it's length property.
With that, you could reduce the array by checking each pair of objects and return the one with the most keys as a one liner:
const biggestObject =
arr.reduce((a, b) => Object.keys(a).length > Object.keys(b).length ? a : b);
I have a big array with data. Here is a example of the structure:
let data = [
{
date: '2018-11-22',
values: {
a: 10,
b: 20,
c: 5,
},
},
{
date: '2018-11-17',
values: {
a: 5,
b: 10,
c: 15,
},
},
{
date: '2018-06-29',
values: {
a: 10,
b: 30,
c: 10,
},
},
{
date: '2017-12-20',
values: {
a: 30,
b: 40,
c: 5,
},
},
];
I need this data structured in a new array by month and year. The value attributes should be summed up for each month.
So the new array for the example should look like this:
let sortedData = [
{
date: '2018-11',
values: {
a: 15,
b: 30,
c: 20,
},
},
{
date: '2018-06',
values: {
a: 10,
b: 30,
c: 10,
},
},
{
date: '2017-12',
values: {
a: 30,
b: 40,
c: 5,
},
},
];
I'm trying for hours to write a working function but I can't handle it.
Any ideas how I can bundle an array like this?
Thanks for your help!
You can use Array.reduce for this
let data = [ { date: '2018-11-22', values: { a: 10, b: 20, c: 5, }, }, { date: '2018-11-17', values: { a: 5, b: 10, c: 15, }, }, { date: '2018-06-29', values: { a: 10, b: 30, c: 10, }, }, { date: '2017-12-20', values: { a: 30, b: 40, c: 5, }, },];
let res = data.reduce((o, {date, values}) => {
let k = date.slice(0, 7)
o[k] = o[k] || {date: k, values: {a: 0, b: 0, c:0}}
o[k].values.a += values.a
o[k].values.b += values.b
o[k].values.c += values.c
return o
}, {})
console.log(Object.values(res))
You can also do make it more concise and not deal with the individual values props like this:
let data = [{ date: '2018-11-22', values: { a: 10, b: 20, c: 5, }, }, { date: '2018-11-17', values: { a: 5, b: 10, c: 15, }, }, { date: '2018-06-29', values: { a: 10, b: 30, c: 10, }, }, { date: '2017-12-20', values: { a: 30, b: 40, c: 5, }, }, ];
const result = data.reduce((r, {date, values}) => {
date = date.substr(0,7)
r[date] = r[date]
? (Object.keys(values).forEach(k => r[date].values[k] += values[k]), r[date])
: {date, values}
return r
}, {})
console.log(Object.values(result))
This way you would not care if there are 3 of 10 properties in values and you get more generic solution.
I have multiple JavaScript objects:
{
a: 12,
b: 8,
c: 17
}
and
{
a: 2,
b: 4,
c: 1
}
I need to sum these two object by keys
Result:
{
a: 14,
b: 12,
c: 18
}
Do you have any solutions in JavaScript?
I use Object.keys.map but it's too long because I have like 100 elements in my object.
You can use reduce for that, below function takes as many objects as you want and sums them by key:
var obj1 = {
a: 12,
b: 8,
c: 17
};
var obj2 = {
a: 12,
b: 8,
c: 17
};
var obj3 = {
a: 12,
b: 8,
c: 17
};
function sumObjectsByKey(...objs) {
return objs.reduce((a, b) => {
for (let k in b) {
if (b.hasOwnProperty(k))
a[k] = (a[k] || 0) + b[k];
}
return a;
}, {});
}
console.log(sumObjectsByKey(obj1, obj2, obj3));
A little bit deeper, all you want as long as objects are equivalent!
const arr = [{
a: 12,
b: { a: 12, c: { a: 12 } },
c: 17
},
{
a: 12,
b: { a: 12, c: { a: 12 } },
c: 17
},
{
a: 12,
b: { a: 12, c: { a: 12 } },
c: 17
}
];
const deepMergeSum = (obj1, obj2) => {
return Object.keys(obj1).reduce((acc, key) => {
if (typeof obj2[key] === 'object') {
acc[key] = deepMergeSum(obj1[key], obj2[key]);
} else if (obj2.hasOwnProperty(key) && !isNaN(parseFloat(obj2[key]))) {
acc[key] = obj1[key] + obj2[key]
}
return acc;
}, {});
};
const result = arr.reduce((acc, obj) => acc = deepMergeSum(acc, obj));
console.log('result: ', result);
Try this.
let t1 =
{
a:12,
b:8,
c:17
};
let t2 =
{
a:2,
b:4,
c:1
};
function sum(ob1, ob2) {
let sum = {};
Object.keys(ob1).forEach(key => {
if (ob2.hasOwnProperty(key)) {
sum[key] = ob1[key] + ob2[key]
}
})
return sum;
}
sum(t1, t2);
https://jsfiddle.net/fbnt2vhe/
If the objects have all common keys, you could take the keys from one object in advance and iterate for creating a new result object and later the keys from the single objects.
var o1 = { a: 12, b: 8, c: 17 },
o2 = { a: 2, b: 4, c: 1 },
keys = Object.keys(o1),
result = [o1, o2].reduce(function (r, o) {
keys.forEach(function (k) {
r[k] += o[k];
});
return r;
}, keys.reduce(function (r, k) {
r[k] = 0;
return r;
}, Object.create(null)));
console.log(result);
If you have just two objects:
const x = { a: 12, b: 8, c: 17 }
const y = { a: 2, b: 4, c: 1 }
const z = Object.fromEntries(Object.keys(x).map(k=>[k,x[k]+y[k]]))
console.log(z)
or, if you have many objects:
const arr = [{ a: 33, b: 44, c: 55 }, { a: 12, b: 8, c: 17 }, { a: 2, b: 4, c: 1 }]
const z = Object.fromEntries(Object.keys(arr[0]).map(k=>[k,arr.reduce((s,o)=>s+o[k],0)]))
console.log(z)