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 am writing some daily challenges for my coding bootcamp and I am running into an issue on one problem. I wrote a function that combines objects and it works correctly. Here is what the problem prompt is
Prompt: Write a function named mergeObjects that accepts at least two objects as arguments, merges the properties of the second through n objects into the first object, then finally returns the first object. If any objects have the same property key, values from the object(s) later in the arguments list should overwrite earlier values.
Examples:
mergeObjects({}, {a: 1}); //=> {a: 1} (same object as first arg)
mergeObjects({a: 1, b: 2, c: 3}, {d: 4}); //=> {a: 1, b: 2, c: 3, d: 4}
mergeObjects({a: 1, b: 2, c: 3}, {d: 4}, {b: 22, d: 44}); //=> {a: 1, b: 22, c: 3, d: 44
My function
function mergeObjects(...obj) {
let obj1 = {}
obj.forEach(element => {
obj1 = {...obj1, ...element}
});
return obj1
}
Solution function
function mergeObjects1(target, ...objects) {
objects.forEach(function (obj) {
// using ES2015's 'for in' loop
for (var key in obj) {
target[key] = obj[key]
}
})
return target
}
In my eyes these two functions provide the same result. However, when I run my code through the jest test they created it fails on the first test. But the solution they provide, does not fail. The jest test is below.
describe('15-mergeObjects', function () {
it('returns same object', function () {
var obj = {}
expect(mergeObjects(obj, { a: 1 })).toBe(obj)
})
it('adds additional properties', function () {
expect(mergeObjects({ a: 1, b: 2, c: 3 }, { d: 4 })).toEqual({
a: 1,
b: 2,
c: 3,
d: 4
})
})
it('merges props from left to right', function () {
expect(
mergeObjects({ a: 1, b: 2, c: 3 }, { d: 4 }, { b: 22, d: 44 })
).toEqual({ a: 1, b: 22, c: 3, d: 44 })
})
})
describe('15-mergeObjects', function () {
it('returns same object', function () {
var obj = {}
expect(mergeObjects1(obj, { a: 1 })).toBe(obj)
})
it('adds additional properties', function () {
expect(mergeObjects1({ a: 1, b: 2, c: 3 }, { d: 4 })).toEqual({
a: 1,
b: 2,
c: 3,
d: 4
})
})
it('merges props from left to right', function () {
expect(
mergeObjects1({ a: 1, b: 2, c: 3 }, { d: 4 }, { b: 22, d: 44 })
).toEqual({ a: 1, b: 22, c: 3, d: 44 })
})
})
Can anyone provide an explanation as to why the solution function passes while my function does not?
While the results look the same, the two functions are slightly different.
In your function, you are creating a new object and then adding to it all of the required properties.
In the solution function, they are adding properties to the original target object and then returning it.
The returned objects from both functions will have the same keys and the same values, but different references, so they are not considered the same object in JavaScript.
In the test
expect(mergeObjects1(obj, { a: 1 })).toBe(obj)
.toBe() checks whether two objects are the same (identity), therefore it fails the case of your function.
Note that there is a different test, .toEqual(), which checks whether two objects have the same keys and the same values (but possibly different references). Your function would pass this test
expect(mergeObjects1(obj, { a: 1 })).toEqual(obj)
I have a CSV file that I have successfully read in with d3.csv. The result is a JSON file where each line consists of an array element and each array element is an object with key/value pairs matching the column headers.
I need this in a "vertical" format, as an array of arrays, where each inner array consists of the value for each object.
Here is an example to run in Node:
> a = new Array();
[]
> a.push({"b":2, "c": 4, "d":6, "e": 8});
1
> a.push({"b":3, "c": 6, "d":9, "e": 12});
2
> a.push({"b":4, "c": 8, "d":12, "e": 16});
3
> a.push({"b":5, "c": 10, "d":15, "e": 20});
4
> a
[
{ b: 2, c: 4, d: 6, e: 8 },
{ b: 3, c: 6, d: 9, e: 12 },
{ b: 4, c: 8, d: 12, e: 16 },
{ b: 5, c: 10, d: 15, e: 20 }
]
> x = [[2,3,4,5],[4,6,8,10],[6,9,12,15],[8,12,16,20]]
[ [ 2, 3, 4, 5 ], [ 4, 6, 8, 10 ], [ 6, 9, 12, 15 ], [ 8, 12, 16, 20 ] ]
> x
[
[ 2, 3, 4, 5 ],
[ 4, 6, 8, 10 ],
[ 6, 9, 12, 15 ],
[ 8, 12, 16, 20 ]
]
>
Here, [a] represents the array of object I have while [x] represents the array of arrays I would like to have.
My data file is very wide and has many columns. I have tried several toy solutions, and I can iterate through the array, select each element, then iterate through each element and select each key, grab the value, and push it to a new array. However, this is nasty and very easy to break. Surely there is a better way.
If I had a list of lists, I could flip the rows and columns. Unfortunately, I have a list of object, read in with D3.csv().
My primary language was (note, was) Perl, and a Perl-ish solution is natural to me. My current application runs client side in a browser, and I need a client side solution in JavaScript.
You can achieve this in a number of ways, but since it appears that all objects in your source array have the same properties, the most direct may be a nested map() call. The outer map() is called on the Object.keys() of the first element of the array, and the inner map() uses each iterated key on every object in the source array.
const a = [{ b: 2, c: 4, d: 6, e: 8 }, { b: 3, c: 6, d: 9, e: 12 }, { b: 4, c: 8, d: 12, e: 16 }, { b: 5, c: 10, d: 15, e: 20 }];
const result = Object.keys(a[0]).map(key => a.map(o => o[key]));
console.log(result);
If the objects had varying properties, you could use a reduce() call to accumulate all the values of like properties.
const a = [{ b: 2, c: 4, d: 6, e: 8 }, { b: 3, c: 6, d: 9, e: 12 }, { b: 4, c: 8, d: 12, e: 16 }, { b: 5, c: 10, d: 15, e: 20 }];
const result = Object.values(
a.reduce((acc, obj) => {
Object.keys(obj).forEach(key =>
(acc[key] ??= []).push(obj[key]));
return acc;
}, {}));
console.log(result);
I like #pilchard's d3 agnostic answer; but if you're interested in a d3 driven answer you can use d3.transpose on an array of arrays with a pre-processing step of removing the keys of the objects with Object.values:
const a = [
{ b: 2, c: 4, d: 6, e: 8 },
{ b: 3, c: 6, d: 9, e: 12 },
{ b: 4, c: 8, d: 12, e: 16 },
{ b: 5, c: 10, d: 15, e: 20 }
]
const x = d3.transpose(a.map(o => Object.values(o)));
console.log(x);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.5.0/d3.min.js"></script>
I have a JS object of the following structure:
let data = {
Apples: {
A: 2,
B: 9
},
Oranges: {
C: 4,
D: 8
},
Bananas: {
E: 3,
F: 2
},
Peaches: {
G: 8,
H: 4
},
Pears: {
I: 10,
J: 10
},
Melons: {
K: 4,
L: 7
}
};
I need to rename the subkey dynamically with JS.
For example, I need to rename the key A into New name.
What is the best ES6-enabled way to do it?
I tried to loop through the object using a simple for loop and generate a new object with a renamed key, but it's indeed not the most efficient way!
What about this?
I'm not generating a new object, but adding the new properties to the existing one and deleting the original ones.
let data = {
Apples: {
A: 2,
B: 9
},
Oranges: {
C: 4,
D: 8
},
Bananas: {
E: 3,
F: 2
},
Peaches: {
G: 8,
H: 4
},
Pears: {
I: 10,
J: 10
},
Melons: {
K: 4,
L: 7
}
};
for (let key1 in data) {
const e = data[key1];
for (let key2 in e) {
e["New Name for " + key2] = e[key2];
delete e[key2];
}
}
console.log(data);
This may have been answered, but I did search.
In js file:
console.log({
a: 1,
b: { c: 1},
d: [{e:1},{f:1}],
g: [{h:[1,2,3]}]
});
This is what actually prints:
{ a: 1,
b: { c: 1 },
d: [ { e: 1 }, { f: 1 } ],
g: [ { h: [Object] } ]
}
Notice 'h' value, can I print this?
Read the docs for util.inspect()
It allows you to specify the depth to print at:
The default is to only recurse twice. To make it recurse indefinitely, pass in null for depth.
To use it, you could call console.log(util.inspect(yourObj, true, null));
console.dir() says it uses util.inspect(), but doesn't show parameters to modify the inspect() call, so it would probably only recurse twice, too.
You can use for loop to iterate over it..
var obj = {
a: 1,
b: {c: 1},
d: [{e: 1}, { f: 1}],
g: [{ h: [1, 2, 3]}]
};
var data = obj.g[0].h ;
for(var i =0; i <data.length ; i++){
console.log(data[i])
}
Check Fiddle
I have used JSON.stringify() to achieve it, you can use parameters to determine the formatting.
As written above, util.inspect() also works.