I made a FIDDLE for you. I am storing a stack string and then output it, if the property is of primitive type:
function iterate(obj, stack) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], stack + '.' + property);
} else {
console.log(property + " " + obj[property]);
$('#output').append($("<div/>").text(stack + '.' + property))
}
}
}
}
iterate(object, '')
Update: 17/01/2019
There used to be a different implementation, but it didn't work. See this answer for a prettier solution
Answer from Artyom Neustroev on Stack OverflowI made a FIDDLE for you. I am storing a stack string and then output it, if the property is of primitive type:
function iterate(obj, stack) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], stack + '.' + property);
} else {
console.log(property + " " + obj[property]);
$('#output').append($("<div/>").text(stack + '.' + property))
}
}
}
}
iterate(object, '')
Update: 17/01/2019
There used to be a different implementation, but it didn't work. See this answer for a prettier solution
The solution from Artyom Neustroev does not work on complex objects, so here is a working solution based on his idea:
function propertiesToArray(obj) {
const isObject = val =>
val && typeof val === 'object' && !Array.isArray(val);
const addDelimiter = (a, b) =>
a ? `
{b}` : b;
const paths = (obj = {}, head = '') => {
return Object.entries(obj)
.reduce((product, [key, value]) =>
{
let fullPath = addDelimiter(head, key)
return isObject(value) ?
product.concat(paths(value, fullPath))
: product.concat(fullPath)
}, []);
}
return paths(obj);
}
const foo = {foo: {bar: {baz: undefined}, fub: 'goz', bag: {zar: {zaz: null}, raz: 3}}}
const result = propertiesToArray(foo)
console.log(result)
EDIT (2023/05/23):
4 different (complete) solutions with full descriptions are available on LeetCode: https://leetcode.com/problems/array-of-objects-to-matrix/editorial/?utm_campaign=PostD19&utm_medium=Post&utm_source=Post&gio_link_id=EoZk0Zy9
java - Is recursion with objects possible? - Stack Overflow
Recursion of Objects
Efficient way to do recursion with objects in Java? - Stack Overflow
Nested object recursion trouble - javascript - Stack Overflow
I assume grid is some complex type, which contains complex types like an array, etc. In this case clone() does not create a deep copy (i.e. it does not recursively clone the parts like an array).
Here is an example of a clone() method for complex types: In this example we have a type FlightLogEntry which contains a TreeMap. To clone a FlightLogEntry we need to create a new TreeMap and fill the map using the original elements. In this example those elements are not cloned (clone.setAttendant(p, this.attendats.get(p)). If you need an even deeper copy from the clone method (which depends on the usage of the clone) you might want to clone the attendat also like this: clone.setAttendant(p, this.attendats.get(p).clone().
@Override
public FlightLogEntry clone() {
FlightLogEntry clone = (FlightLogEntry) super.clone();
clone.attendants = new TreeMap<Person, Duty>();
for( Person p : this.attendants.keySet() ) {
clone.setAttendant(p, this.attendants.get(p));
}
return clone;
}
You need to instantiate a new grid object in your Program(grid) constructor, then assign the values from the old grid with the new one.
To the extent an answer exists to so generic a question (and understanding the rationale for the generality), it is persistent data structures. These are what is used to do efficient computation in languages like Haskell where everything is immutable and all algorithms are based on recursion, so they are certainly appropriate for your case. That said, Java is not optimized for such operations, so you may find that solutions that sound clumsier are faster to code and/or execute in practice.
If you need your List or Array of something as it has been before, then you can just copy it once before modifying the copied version recursively, but you don't need to copy it at every recursive step.
This exhibits a classic recursion antipattern: passing the result (sum) down the call stack as a parameter while also trying to pass it up as a result, leading to a confused state of affairs and double-counting.
Here's a fundamental rule of thumb for recursion: data dependencies (the things used to compute a result) are the parameters, results are return values.
Make sum local to the frame, then accumulate on it during the frame, either because each element is a number (leaf node in the tree search) or it's a child that should be explored recursively. Don't return immediately in the loop or you will miss some of the children.
function nestedEvenSum(obj) {
let sum = 0;
for (const k in obj) {
if (obj[k].constructor === Object) {
sum += nestedEvenSum(obj[k]);
}
else if (typeof obj[k] === "number" && obj[k] % 2 === 0) {
sum += obj[k];
}
}
return sum;
}
const obj = {
a: 2,
c: {
c: {
c: 2
},
cc: 'b',
ccc: 5
},
e: {
e: {
e: 2
},
ee: 'car'
}
};
console.log(nestedEvenSum(obj));
Note that this algorithm ignores arrays.
Also note that the function's design is highly rigid due to the % 2 === 0 predicate. You might consider using a function that traverses any nested structure and returns an array or generator of results that can then be filtered, or a function that allows an arbitrary callback predicate to perform the filtering.
One exception to the one-way data flow rule is that sometimes you'll want to accumulate results onto a parameter array as an optimization rather than returning and merging multiple arrays as you move back up the call stack, but that doesn't apply here.
I think I figured it out.
First, you're returning if you find an object, which means you'll stop early, so I removed the early 'return'.
Second, you're double-counting if you find an object, because you're passing in the sum you already have and then adding it to the sum you already have.
Check this out, just a couple small changes:
function nestedEvenSum(obj, sum = 0) {
for(const k in obj) {
if (obj[k].constructor === Object) {
sum = nestedEvenSum(obj[k], sum);
}
if (typeof obj[k] === "number" && obj[k] % 2 === 0) {
sum += obj[k];
}
}
return sum;
}
const obj = {
a: 2,
c: {c: {c: 2}, cc: 'b', ccc: 5},
e: {e: {e: 2}, ee: 'car'}
}
console.log(nestedEvenSum(obj));