繁体   English   中英

在 F# 中,如何正确使用 ResizeArray() 和 Array.map 中的累加器来更改记录的属性

[英]In F#, how to correctly use ResizeArray() and an accumulator in an Array.map to change the property of a record

(新手问题)。 简单的问题。

在 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”中的累加器为游标数组中的每个 Cursor 计算一个新的 TopLeft 值,并返回一个新的游标数组,其中每个 cursor 记录具有其新值。

这是如何正确完成的? 可以在不使用可变“左”变量的情况下完成吗?

先感谢您。

#附录:“列”定义为整数数组(每个 integer 代表一列的宽度)。

 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

output 为: 100,330,690,910

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM