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 ano开发者_如何学Pythonther 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?
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.
精彩评论