Обмен большими списками между C# и F#
У меня есть большие файлы данных исторических данных о запасах, которые я хочу загрузить через графический интерфейс C#, а затем обработать различными алгоритмами в F#. Дополнительные значения добавляются в списки с течением времени.
Списки двумерные и в форме
[[id, Open,High,Low,Close], [id, Open,High,Low,Close], ...]
Код F# находится в библиотеке и не может работать со списками C# (я не могу получить значения второго измерения списка в F#). Преобразование всего списка каждый раз, когда выполняется операция F#, слишком дорого. Значения также не могут быть сохранены в списке F#, потому что C# не может их обработать.
Предлагаемые решения:
либо сохранение списка F# в C#, просто для целей хранения, поскольку библиотека не может хранить значения вместе со списком C#, содержащим те же значения, преобразуя части списка по мере необходимости. Основная проблема заключается в том, что файлы могут иметь размер несколько ГБ.
чтение значений, которые необходимы непосредственно из файла в F# и сохранение вычисленных значений в дополнительных файлах. Проблема здесь заключается в эффективной организации файлов, так что выбор строк (например, для вычисления скользящего среднего) для загрузки может быть сделан быстро.
2 ответа
Должна ли внутренняя последовательность быть списком? Если он всегда имеет одни и те же элементы (OHLC), было бы лучше использовать кортеж (или пользовательский тип), поскольку он явно указывает на его фиксированную природу. Я бы, наверное, сделал что-то вроде этого:
module Stock =
let (!) s = DateTime.Parse(s)
let getOHLC() : unit -> seq<DateTime * float * float * float * float> =
seq [
!"18-Dec-12",27.25,27.63,27.14,27.56
!"17-Dec-12",26.79,27.22,26.68,27.10
!"14-Dec-12",27.11,27.13,26.70,26.81
//...
]
Если вам действительно нужно, чтобы каждый элемент был списком, вы можете передать его через Seq.map seq
,
seq
функция определяется как:
let seq (x:seq<'T>) = x
так что это только гадости, а не копирование.
Преобразование всего списка каждый раз, когда выполняется операция F#, слишком дорого.
Вы измерили это?
Значения также не могут быть сохранены в списке F#, потому что C# не может их обработать.
Вы должны иметь возможность перечислять элементы списка F# из C#, потому что это просто еще один перечисляемый элемент.
Тип в C# это
System.Generics.List<System.Generics.List<Double>>
и передается какIEnumerable
в F#. Не звонитOfSeq()
преобразование значения списка, заставляя меня перебирать весь вызов спискаOfSeq()
на каждом элементе и, следовательно, дублировать его.
Называть что-то вроде Array.ofSeq
создаст новую коллекцию, но вам не нужно делать это для перебора содержимого.
Обратите внимание, что имя F# для указанного вами типа ResizeArray<ResizeArray<float>>
,
Например, вы можете сделать:
let f (xss: ResizeArray<ResizeArray<float>>) =
for xs in xss do
for x in xs do
printfn "%A" x
потреблять ваши данные из F# без копирования.