gpt4 book ai didi

javascript - FP:树木-分别映射,折叠。怎么样?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:05:33 25 4
gpt4 key购买 nike

我有一个working OOP code递归地将图形元素的组合呈现到画布上。有很多人不喜欢它,我想看看功能版本会是什么样子。
当然,可以编写专门的递归纯函数,但由于框架涉及类似的算法,我想:
利用功能组合的力量。
看看fp-及其数据管道范例(通过纯函数转换数据)如何将自身定位到比列表(树/图)更复杂的结构和更少琐碎的算法(比如,通过顺序迭代列表来查找所有奇数)。
受到Lazy.js的启发,我开始编写代码,并取得了以下成果:

LazyTree.from( drawing )
.keepNodes( visible )
.keepChildrenOf( nonClipping )
.traverse( log );

但是关于地图和折叠,我有很多问题没有回答。
目标
下面是我要解决的问题的简化版本:
数据
矩形的组合(层次)它们的边界都在相对坐标中(相对于其父对象):
const drawing = {
name: 'Face',
bounds: { x: 10, y: 10, w: 100, h: 100 },
children: [{
name: 'Left eye',
bounds: { x: 10, y: 10, w: 20, h: 20 }, // Abs: (20, 20, 20, 20)
children: [{
name: 'Left pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (25, 25, 10, 10)
}]
},{
name: 'Right eye',
bounds: { x: 70, y: 10, w: 20, h: 20 }, // Abs: (80, 20, 20, 20)
children: [{
name: 'Right pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (85, 25, 10, 10)
}]
}]
};

任务-GetAbsoluteBounds
任务是将此合成转换为具有绝对坐标的合成(如注释中所示)。
问题和想法
折叠?
子级的绝对坐标是由父级绝对坐标转置的相对坐标。所以一个带累加器的折叠就可以做到这一点。
但是fold与变形和combine等动词相关,通常返回一个值。
所讨论的转换采用一棵树并返回一个相同的结构,但具有不同的值-因此它听起来更像一个映射,但它需要一个累加器。
就累加器而言,值得注意的是,特定节点的所有子节点都应该得到相同的累加器。对于上面的数据, Left eyeRight eye都应该得到 Face的绝对坐标(而不是 Right eye在深度第一次遍历中得到 Left eye的返回累加器)。
另一件我不清楚的事情是谁应该负责构建输出树。它应该是高阶函数(fold、map或其他函数),还是应该是聚合器?
停止条件
关联上一节,考虑所有矩形来剪裁其子对象,以及以下组合:
const drawing = {
name: 'Parent',
bounds: { x: 10, y: 10, w: 10, h: 10 },
children: [{
name: 'Child',
bounds: { x: 1000000, y: 1000000, w: 10, h: 10 },
children: [{
name: 'Grandchild',
bounds: { x: 5, y: 5, w: 5, h: 5 }
}]
}]
};

Child界限相对于其父级( Parent)超出界限,因此当遍历到 Child时,分支遍历应停止(没有点遍历到 Grandchild)。
问题是:如何用fold函数实现这一点?一种解决方案是当累加器返回一个商定的值(比如 undefined)时停止分支遍历但这与列表的fold API有些不同。
访问前后
渲染算法包括:
fill( shape );
renderChildren( shape );
stroke( shape );

我想知道如何通过 traverse()each()这样的方法来实现这一点这需要两次回拨吗(前,后)?
穿越策略
树遍历可以是:
深度或广度优先。
自上而下或自下而上(对于后者, see a specialised example for transforming an AST,使用reduce)。
对于列表,我们有类似于 reverse()的函数。Lazy.js允许 adding a custom iterator链接。
因此,处理遍历策略的fp方法似乎是一个转换函数。还有别的事吗?
摘要
在使用数据管道模型实现树结构的呈现算法时,我已经谈到了一些挑战。
我怀疑是否还有其他的FP方法更适合这里也许数据管道模型不适合这些问题。或者,我应该忘记在FP库中看到的api(它几乎只处理列表),创建一个适合手头任务的api(例如,有一个map函数也包含一个累加器)。
我找不到任何专门用于树的fp库,那里的信息通常仅限于非常简单的问题。
所以,希望有人会用这样的话来回答:“这是应该怎么做的”。

最佳答案

就我所知,你可以这样做。
它将继续遍历留在父级边界内的那些项,将它们的坐标转换为绝对坐标,然后再渲染它们。但是,如果子对象的边界与父对象的边界重叠,则跳过子对象及其子对象。不会转换为绝对坐标,也不会对这些坐标进行渲染。

function render(bounds){
console.log("Rendered:", bounds);
}

function relToAbs(o, b = {x: 0, y:0, w:Infinity, h:Infinity}, go = true){
go = o.bounds.x < b.w && o.bounds.y < b.h ? (o.bounds.x += b.x, o.bounds.y += b.y, render(o.bounds), go) : !go;
o.children && go && (o.children = o.children.map(p => relToAbs(p,o.bounds,go)));
return o;
}

var drawing = { name: 'Face',
bounds: { x: 10, y: 10, w: 100, h: 100 },
children: [{ name: 'Left eye',
bounds: { x: 200, y: 10, w: 20, h: 20 }, // Abs: (20, 20, 20, 20)
children: [{ name: 'Left pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (25, 25, 10, 10)
}]
},
{ name: 'Right eye',
bounds: { x: 70, y: 10, w: 20, h: 20 }, // Abs: (80, 20, 20, 20)
children: [{ name: 'Right pupil',
bounds: { x: 5, y: 5, w: 10, h: 10 } // Abs: (85, 25, 10, 10)
}]
}]
};
console.log(JSON.stringify(relToAbs(drawing),null,2));

关于javascript - FP:树木-分别映射,折叠。怎么样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41753599/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com