F# 父/子列表到 Excel

发布于 2024-12-08 05:28:38 字数 1067 浏览 1 评论 0原文

我对 F# 还很陌生,所以希望我的问题不会太愚蠢。我正在创建一个 Excel 文件。我已经用 C# 完成了很多 Excel 工作,所以这不是问题。我有一个父行列表,然后是一个子行列表。将其吐入 Excel 并跟踪 Excel 中它所属的行的最佳方法是什么。

假设我的列表 rowHdr 是 Row 类型的列表,我会遇到这样的问题:

let setCellText (x : int) (y : int) (text : string) = 
   let range = sprintf "%c%d" (char (x + int 'A')) (y+1)
   sheet.Range(range).Value(Missing.Value) <- text

type Row = 
    {   row_id:string
        parent_id:string
        text:string }

let printRowHdr (rowIdx:int) (colIdx:int) (rowToPrint:Row) rows = 
    setCellText colIdx rowIdx rowToPrint.text

List.iteri (fun i x -> printRowHdr (i+1) 0 x rows) <| rowHdr

我仍然无法思考最佳的功能方法是什么有时是。在 printRowHdr 函数中的某个位置,我需要迭代子行以查找parent_id 等于父行id 的行。我的麻烦是知道它属于 Excel 中的哪一行。也许这是完全错误的方法,但我很感激任何建议。

感谢您的任何帮助,我衷心感谢。

谢谢, 尼克

编辑添加:

托马斯 - 感谢您的帮助。假设我有两个列表,一个包含美国各州,另一个包含城市。城市列表还包含州缩写。我想遍历各州,然后获取每个州的城市。因此,它在 Excel 中可能看起来像这样:

Alabama 
    Montgomery 
California 
    San Francisco 
Nevada 
    Las Vegas 
etc... 

给定这两个列表,我可以以某种方式将它们加入到一个列表中吗?

I'm still new to F# so hopefully my question isn't too dumb. I'm creating an Excel file. I've done a lot of Excel with C# so that isn't a problem. I have a list of parent rows and then a list of child rows. What's the best way to spit that into Excel and keep track of the row in Excel that it belongs in.

Assuming my list rowHdr is a list of Row types, I have something like this:

let setCellText (x : int) (y : int) (text : string) = 
   let range = sprintf "%c%d" (char (x + int 'A')) (y+1)
   sheet.Range(range).Value(Missing.Value) <- text

type Row = 
    {   row_id:string
        parent_id:string
        text:string }

let printRowHdr (rowIdx:int) (colIdx:int) (rowToPrint:Row) rows = 
    setCellText colIdx rowIdx rowToPrint.text

List.iteri (fun i x -> printRowHdr (i+1) 0 x rows) <| rowHdr

I still have trouble thinking about what the best functional approach is at times. Somewhere in the printRowHdr function I need to iterate through the child rows for the rows where the parent_id is equal to parent row id. My trouble is knowing what row in Excel it belongs in. Maybe this is totally the wrong approach, but I appreciate any suggestions.

Thanks for any help, I sincerely appreciate it.

Thanks,
Nick

Edited to add:

Tomas - Thanks for the help. Let's say I have two lists, one with US states and another with cities. The cities list also contains the state abbreviation. I would want to loop through the states and then get the cities for each state. So it might look something like this in Excel:

Alabama 
    Montgomery 
California 
    San Francisco 
Nevada 
    Las Vegas 
etc... 

Given those two lists could I join them somehow into one list?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

○闲身 2024-12-15 05:28:38

我不完全确定我是否理解你的问题 - 给出一个包含一些输入的具体示例以及你想要获取的 Excel 工作表的屏幕截图将非常有用。

然而,使用ID来建模父/子关系(如果这就是您想要做的)的想法听起来不像是最好的功能方法。我想您正在尝试表示这样的内容:

First  Row
       Foo  Bar
       Foo  Bar
Second Row
       More Stuff Here
            Some  Even  More  Neste  Stuff

这可以使用递归类型来表示,该递归类型包含当前行中的项目列表,然后是子行列表(它们本身可以包含子行):

type Row = Row of list<string> * list<Row>

然后您可以处理使用递归函数的结构。值的示例(代表上面示例中的前三行)可能是:

Row( ["First"; "Row"],
     [ Row( ["Foo"; "Bar"], [] )
       Row( ["Foo"; "Bar"], [] ) ])

EDIT: 如果您有任意嵌套,上面的 Row 类型将很有用。如果您只有两层(州和城市),那么您可以使用列表列表。另一个列表包含州名称以及包含该州所有城市的嵌套列表。

如果您从两个列表开始,那么您可以使用几个 F# 函数将输入转换为列表列表:

let states = [ ("WA", "Washington"); ("CA", "California") ]
let cities = [ ("WA", "Seattle"); ("WA", "Redmond"); ("CA", "San Francisco") ]

cities
// Group cities by the state
|> Seq.groupBy (fun (id, name) -> id)
|> Seq.map (fun (id, cities) ->
    // Find the state name for this group of cities
    let _, name = states |> Seq.find (fun (st, _) -> st = id)
    // Return state name and list of city names
    name, cities |> Seq.map snd)

然后您可以递归地迭代嵌套列表(在上面,它们实际上是序列,因此您可以将它们使用List.ofSeq列表)并保留当前行和列的索引。

I'm not entirely sure if I understand your question - giving a concrete example with some inputs and a screenshot of the Excel sheet that you're trying to get would be quite useful.

However, the idea of using ID to model parent/child relationship (if that's what you're trying to do) does not sound like the best functional approach. I imagine you're trying to represent something like this:

First  Row
       Foo  Bar
       Foo  Bar
Second Row
       More Stuff Here
            Some  Even  More  Neste  Stuff

This can be represented using a recursive type that contains the list of items in the current row and then a list of children rows (that themselves can contain children rows):

type Row = Row of list<string> * list<Row>

You can then process the structure using recursive function. An example of a value (representing first three lines from the example above) may be:

Row( ["First"; "Row"],
     [ Row( ["Foo"; "Bar"], [] )
       Row( ["Foo"; "Bar"], [] ) ])

EDIT: The Row type above would be useful if you had arbitrary nesting. If you have just two layers (states and cities), then you can use list of lists. The other list containing state name together with a nested list that contains all cities in that state.

If you start with two lists, then you can use a couple of F# functions to turn the input into a list of lists:

let states = [ ("WA", "Washington"); ("CA", "California") ]
let cities = [ ("WA", "Seattle"); ("WA", "Redmond"); ("CA", "San Francisco") ]

cities
// Group cities by the state
|> Seq.groupBy (fun (id, name) -> id)
|> Seq.map (fun (id, cities) ->
    // Find the state name for this group of cities
    let _, name = states |> Seq.find (fun (st, _) -> st = id)
    // Return state name and list of city names
    name, cities |> Seq.map snd)

Then you can recursively iterate over the nested lists (in the above, they are actually sequences, so you can turn them to lists using List.ofSeq) and keep an index of the current row and column.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文