"Write a function arrayToList that builds up a list structure like"
let LL = { data: 1, next: { data: 2, next: { data: 3, next: null }}};
I understand the typical solution to this problem, where the list must be built from the inside out:
function arrToLList(arr) {
let LList = null;
for (let i = arr.length - 1; i >= 0; i--) {
LList = { data: arr[i], next: LList };
}
return LList;
}
But my initial solution was to brute force it with a typical for loop.
function arrayToLList(arr) {
let d = "data";
let n = "next";
let LList = nextNode();
for (let i = 0; i < arr.length; i++) {
LList[d] = arr[i];
d = "next." + d;
LList[n] = nextNode();
n = "next." + n;
}
function nextNode() {
return {
data: null,
next: null
};
}
return LList;
}
What you want to achieve is possible, but you need to customize the functionality of how getting a property works when you use bracket notation. As you mentioned, using dot notation with bracket notation won't work, you need a way to define this logic yourself. ES6 introduced Proxies which allows you to specify a set method trap for your object. Whenever you set a value on the object, the set method will be called. Using this idea, you can split the dot-notation string by .
and traverse the path it returns to get your nested object. Once you have retrieved the nested object, you can set its value.
See example below:
function arrayToLList(arr) {
let d = "data";
let n = "next";
let LList = nextNode();
for (let i = 0; i < arr.length; i++) {
LList[d] = arr[i];
d = "next." + d;
if(i < arr.length-1) // don't add null object to last node
LList[n] = nextNode();
n = "next." + n;
}
function nextNode() {
const obj = {
data: null,
next: null
};
return new Proxy(obj, {
set: function(obj, key, val) {
const path = key.split('.');
const last = path.pop();
for(const prop of path)
obj = obj[prop];
obj[last] = val;
return true;
}
});
}
return LList;
}
console.log(arrayToLList([1, 2, 3]));
However, you don't need to use a proxy. A more straightforward way of doing this would be by creating a method such as setValueByPath(val, obj, strPath)
which performs the logic in the proxy for you. Then, instead of setting your object using bracket notation, you simply call the setValueByPath(obj, strPath)
:
function setValudByPath(val, obj, strPath) { // pefroms same logic from proxy, just using reduce instead
const path = strPath.split('.');
const last = path.pop();
path.reduce((nested, p) => nested[p], obj)[last] = val;
}
function arrayToLList(arr) {
let d = "data";
let n = "next";
let LList = {data: null, next: null};
for (let i = 0; i < arr.length; i++) {
setValudByPath(arr[i], LList, d); // same as LList[d] = arr[i];
d = "next." + d;
if(i < arr.length-1) // don't add null object to last node
setValudByPath({data: null, next: null}, LList, n); // same as: LList[n] = nextNode();
n = "next." + n;
}
return LList;
}
console.log(arrayToLList([1, 2, 3]));