arrays - 在 F# 中,如何正确使用 ResizeArray() 和 Array.map 中的累加器来更改记录的属性
问题描述
(新手问题)。简单的问题。
在 C# 中,我有以下代码:
double openspace = (WorkArea.Width - totalcolumnwidth) / (ColumnCount - 1);
double left = WorkArea.Left;
for (int k = 0; k < ColumnCount; k++)
{
Cursor cursor = new Cursor
{
TopLeft = new Point(left, WorkArea.Top),
};
cursors.Add(cursor);
left += Columns[k] + openspace;
}
在 F# 中,为了简单起见,我尝试过这样做,但它失败了。
type Cursor = { TopLeft: float }
let columnCount = 5.0 // // columnCount number of cursors in List<Cursor>
let cursors = new ResizeArray<Cursor>(columnCount)
let mutable left = 20.0
cursors |> Array.map ( fun k -> left <- left + 10 + k.TopLeft ; {k with TopLeft = left} )
这里的目标是根据“left”中的累加器为游标数组中的每个游标计算一个新的 TopLeft 值,并返回一个新的游标数组,每个游标记录都有其新值。
这是如何正确完成的?可以在不使用可变“左”变量的情况下完成吗?
先感谢您。
#Addendum:“列”被定义为一个整数数组(每个整数代表一列的宽度)。
columns = [|210; 330|]
解决方案
我认为您不需要 fold (或更准确地说是scan)来处理此问题,因为TopLeft
实际上可以在不参考先前值的情况下计算当前TopLeft
值。这是数组理解的一个很好的例子。像这样的东西:
let cursors =
[|
for i = 0 to columnCount-1 do
yield { TopLeft = initialOffset + (columnOffset * float i) }
|]
这是有效的,因为列是恒定宽度的。对于可变宽度列,您肯定需要扫描,如下所示:
let columnWidths = [| 210; 340; 200; 300 |]
let initialOffset = 100 // left coord of first column
let columnOffset = 20 // gap between columns
let columnLefts =
(initialOffset, columnWidths)
||> Seq.scan (fun acc width ->
acc + width + columnOffset)
|> Seq.take columnWidths.Length // ignore final value
|> Seq.toArray
printfn "%A" columnLefts
输出是:100,330,690,910
推荐阅读
- ruby-on-rails - Rails 5.2.1 - 模型和片段缓存
- php - Laravel 4.2 走错路了
- powershell - 无法通过 Powershell 找到证书:驱动器或证书提供程序
- aerospike - 在没有索引的情况下看到具有 4G 的 memory_used_index_bytes
- c# - 在 Roslyn Fixer 中获取样式设置
- sql-server - BCP 实用程序 - 忽略导入文件中的默认值
- javascript - 用于添加到购物车的 redux concat 数组
- python - 使用两个或多个不同的键查找 django 模型
- node.js - 无法从最新的 nodejs LTS 安装程序中获取正确的 NPM 版本
- laravel - 不同视图的 Laravel 路径