我正在尝试在Javascript中实现DLX,而且我遇到了更新自引用对象文字的问题。
此函数采用二进制矩阵并返回一个矩阵,其中矩阵的每个“1”都是一个对象,引用它在所有基本方向上都是“1”。
cascade={"persist"}
之前我遇到了一个问题,当我遇到在对象文字声明and was suggested to use getters中创建自引用的问题时。现在在DLX中,数据结构中的对象需要能够更改。 如何创建可编辑的自引用对象文字?
我相信这个问题可以简化为
export const constructDataObjects = matrix => {
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix.length; j++) {
let u = j - 1;
let d = j + 1;
let l = i - 1;
let r = i + 1;
if (matrix[i][j] === 0) continue;
// Check edge cases.
if (u < 0) u = matrix.length - 1;
if (d >= matrix.length) d = 0;
if (l < 0) l = matrix.length - 1;
if (r >= matrix.length) r = 0;
// Increment and decrement directions, with bound checks.
// On hitting a bound, circle around and start from the other side.
while (matrix[i][u] === 0) u = u - 1 < 0 ? matrix.length - 1 : u - 1;
while (matrix[i][d] === 0) d = d + 1 >= matrix.length ? 0 : d + 1;
while (matrix[l][j] === 0) l = l - 1 < 0 ? matrix.length - 1 : l - 1;
while (matrix[r][j] === 0) r = r + 1 >= matrix.length ? 0 : r + 1;
matrix[i][j] = {
_u: undefined,
_d: undefined,
_l: undefined,
_r: undefined,
get u () { return this._u },
set u (v) { return this._u = v },
get d () { return this._d },
set d (v) { return this._d = v },
get l () { return this._l },
set l (v) { return this._l = v },
get r () { return this._r },
set r (v) { return this._r = v },
c : null,
debug: `i:${i}, j:${j}, u:${u}, d:${d}, l:${l}, r:${r}`
};
matrix[i][j].u = matrix[i][u]
matrix[i][j].d = matrix[i][d]
matrix[i][j].l = matrix[l][j]
matrix[i][j].r = matrix[r][j]
}
}
return matrix;
};
为清楚起见,我将let a = arr => {
for(let i = 0; i < arr.length; i++) {
arr[i] = {
curr: arr[i],
first: arr[0],
last: arr[arr.length - 1],
}
}
return arr
}
console.log(a([1,2]))
表示为*first
中对象的引用
和arr[0]
作为*second
中对象的引用。
现在arr[1]
生成
a([1,2])
我想要的是
[ { curr: 1, first: 1, last: 2 },
{ curr: 2, first: *first, last: 2 } ]
添加getters
[ { curr: *first, first: *first, last: *second } },
{ curr: *second, first: *first, last: *second } ]
现在let a = arr => {
for(let i = 0; i < arr.length; i++) {
arr[i] = {
get curr () { return arr[i] },
get first () { return arr[0] },
get last () { return arr[arr.length - 1] }
}
}
return arr
}
console.log(a([1,2]))
产生我想要的东西
a([1,2])
让我们添加更新对象的功能。 这是我被困的地方。 这是我尝试过的,它不起作用:
[ { curr: *first, first: *first, last: *second } },
{ curr: *second, first: *first, last: *second } ]
从控制台输出let a = arr => {
for(let i = 0; i < arr.length; i++) {
arr[i] = {
_curr: undefined,
_first: undefined,
_last: undefined,
get curr () { return this._curr },
set curr (v) { this._curr = v },
get first () { return this._first },
set first (v) { this._first = v },
get last () { return this._last },
set last (v) { this._last = v },
}
arr[i].curr = arr[i]
arr[i].first = arr[0]
arr[i].last = arr[arr.length - 1]
}
return arr
}
console.log(a([1,2]))
可以看出
a([1,2])
我想要的是
[ { curr: *first, first: *first, last: 2 },
{ curr: *second, first: *first, last: *second } ]
如何通过使用getter来保持行为,同时还允许对象可更新?
答案 0 :(得分:1)
在创建该对象之前,不能创建引用对象的属性。我建议你给每个单元格一个getter方法(或属性),它在调用时访问下一个单元格,而不是在构造单元格时。
export function constructDataObjects(matrix) {
const size = matrix.length; // assumed quadratic
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
if (matrix[i][j] === 0) continue;
// Increment and decrement directions, with bound checks.
// On hitting a bound, circle around and start from the other side.
let u = j;
do { u--; if (u < 0) u = size - 1; } while (matrix[i][u] === 0);
let d = j;
do { d++; if (d >= size) d = 0; } while (matrix[i][d] === 0);
let l = i;
do { l--; if (l < 0) l = size - 1; } while (matrix[l][j] === 0);
let r = i;
do { r++; if (r >= size) r = 0; } while (matrix[r][j] === 0);
matrix[i][j] = {
u,
d,
l,
r,
getUp() { return matrix[i][this.u] },
getDown() { return matrix[i][this.d] },
getLeft() { return matrix[this.l][j]; },
getRight() { return matrix[this.r][j]; },
c : null,
debug: `i:${i}, j:${j}, u:${u}, d:${d}, l:${l}, r:${r}`
};
}
}
return matrix;
}
或者,要真正创建循环结构,首先应使用空属性创建对象,然后再填充它们。你甚至可以避免在两个方向上进行迭代。
export function constructDataObjects(matrix) {
const size = matrix.length; // assumed quadratic
for (let i = 0; i < size; i++) {
for (let j = 0; j < size; j++) {
if (matrix[i][j] !== 0) {
matrix[i][j] = {
i,
j,
u: null,
d: null,
l: null,
r: null,
c: null
};
}
}
}
for (let i = 0; i < size; i++) {
let j = 0;
while (matrix[i][j] === 0 && j < size) j++;
const first = matrix[i][j];
let cur = first;
while (j < size) {
do { j++; } while (j < size && matrix[i][j] === 0);
const next = matrix[i][j];
cur.d = next;
next.u = cur;
cur = next;
}
if (first) {
cur.d = first;
first.u = cur;
}
}
for (let j = 0; j < size; j++) {
let i = 0;
while (matrix[i][j] === 0 && i < size) i++;
const first = matrix[i][j];
let cur = first;
while (i < size) {
do { i++; } while (i < size && matrix[i][j] === 0);
const next = matrix[i][j];
cur.r = next;
next.l = cur;
cur = next;
}
if (first) {
cur.r = first;
first.l = cur;
}
}
return matrix;
}