#f#
#f#
Вопрос:
Я все еще новичок в F #, так что, надеюсь, мой вопрос не слишком глуп. Я создаю файл Excel. Я много работал с Excel на C #, так что это не проблема. У меня есть список родительских строк, а затем список дочерних строк. Каков наилучший способ перенести это в Excel и отслеживать строку в Excel, к которой она принадлежит.
Предполагая, что мой список rowHdr представляет собой список типов строк, у меня есть что-то вроде этого:
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 равен идентификатору родительской строки. Моя проблема в том, чтобы знать, к какой строке в Excel она принадлежит. Возможно, это совершенно неправильный подход, но я ценю любые предложения.
Спасибо за любую помощь, я искренне ценю это.
Спасибо, Ник
Отредактировано для добавления:
Томас — Спасибо за помощь. Допустим, у меня есть два списка: один со штатами США, а другой с городами. Список городов также содержит сокращение штата. Я бы хотел перебрать штаты, а затем получить города для каждого штата. Так что в Excel это может выглядеть примерно так:
Alabama
Montgomery
California
San Francisco
Nevada
Las Vegas
etc...
Учитывая эти два списка, могу ли я как-то объединить их в один список?
Ответ №1:
Я не совсем уверен, правильно ли я понимаю ваш вопрос — было бы весьма полезно привести конкретный пример с некоторыми входными данными и скриншотом таблицы 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"], [] ) ])
РЕДАКТИРОВАТЬ: 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
) и сохранить индекс текущей строки и столбца.
Комментарии:
1. Томас — Спасибо за помощь. Я отредактировал свой первоначальный вопрос с помощью примера.
2. @nickfinity Пример был очень полезен — я добавил несколько вещей к своему ответу.
3. Большое спасибо. У меня никогда не должно быть более двух уровней. Большое вам спасибо за вашу помощь.