this post was submitted on 14 Feb 2024
6 points (100.0% liked)

Programming

424 readers
7 users here now

Welcome to the main community in programming.dev! Feel free to post anything relating to programming here!

Cross posting is strongly encouraged in the instance. If you feel your post or another person's post makes sense in another community cross post into it.

Hope you enjoy the instance!

Rules

Rules

  • Follow the programming.dev instance rules
  • Keep content related to programming in some way
  • If you're posting long videos try to add in some form of tldr for those who don't want to watch videos

Wormhole

Follow the wormhole through a path of communities !webdev@programming.dev



founded 2 years ago
MODERATORS
 

Intended output: { children: { Display: { children: { ... value: 2 } } } }

Real output: { children: {}, Display: {}, ... value: 2 }


Code:

// Load default settings
let defaultSettings;

load("/assets/json/default-settings.json", 'json', function(defset) {
	defaultSettings = defset;

	// Create custom settings
	if(!Object.keys(localStorage).includes('settings')) {
		setLs('settings', JSON.stringify({}));
	};

	customiseSetting('Display/UI/Distance', 2)
});

function settingURL(url) {
	return('children/' + url.split('/').join('/children/') + '/value');
}

function customiseSetting(url, value) {
	url = settingURL(url);

	// Split the string by '/' and use reduce to access the nested properties
	const newSettings = url.split('/').reduce(function(accumulator, val, index, array) {
		// If the object does not have the current component as a property, create an empty object for it
	  	// If the current component is the last one, assign the value
	  	if (index == array.length - 1) {
			accumulator[val] = value;
	  	} else if (!accumulator.hasOwnProperty(val)) {
			accumulator[val] = {}; // update the accumulator object
		}

		log([accumulator, val, index, array])
		// Return the updated object
	  	return(accumulator);
	}, JSON.parse(ls('settings')));
	log(newSettings);
	setLs('settings', JSON.stringify(newSettings));
}

I've been trying unsuccessfully for several days to fix to what must be a simple error. I've looked over it myself, but I can't find the cause of the bug. I asked Bing, which usually helps, but it was unhelpful. So I'm sorry to be bothering you, but if you could help me solve this problem, I would really appreciate it.

EDIT: I fixed my code by using a recursive function as follows:

function customiseSetting(url, value) {
	url = settingURL(url).split('/');

	let newSettings;

	function recursiveSet(object, list, index, setTo) {
		// If the current component is the last one, assign the value
		if(index == list.length - 1) {
			object[list[index]] = setTo;
			return(object);
		} else {
			// Check if it already contains the value
			if(object.hasOwnProperty(list[index])) {
				object[list[index]] = recursiveSet(object[list[index]], list, index + 1, setTo);
			} else {
				object[list[index]] = recursiveSet({}, list, index + 1, setTo);
			}
			return(object);
		}
	};

	newSettings = recursiveSet(JSON.parse(ls('settings')), url, 0, value);

	log(newSettings);
	setLs('settings', JSON.stringify(newSettings));
}
top 4 comments
sorted by: hot top controversial new old
[–] DmMacniel@feddit.de 2 points 11 months ago* (last edited 11 months ago) (1 children)

Look at your settingURL function.

You always prepend a children/ to the URL. Then you split the incoming URL up into an array and concatenate the elements with children/.

So it will become something like children/Display/children/UI/

[–] JackGreenEarth@lemm.ee 1 points 11 months ago

Yes, that's intentional. What's not intentional is that they are all direct children of the parent object, rather than children of each other

[–] Spzi@lemm.ee 2 points 11 months ago

You can use more debug outputs (log(...)) to narrow it down. Challenge your assumptions! If necessary, check line by line if all the variables still behave as expected. Or use a debugger if available/familiar.

This takes a few minutes tops and guarantees you to find at which line the actual behaviour diverts from your expectations. Then, you can make a more precise search. But usually the solution is obvious once you have found the precise cause.

[–] Lixen 1 points 11 months ago* (last edited 11 months ago)

Build the object from the inside out.

Add .reverse() in front of the .reduce, and then simply return { [val]: accumulator } each iteration of the reduce