Обмен большими списками между C# и F#

У меня есть большие файлы данных исторических данных о запасах, которые я хочу загрузить через графический интерфейс C#, а затем обработать различными алгоритмами в F#. Дополнительные значения добавляются в списки с течением времени.

Списки двумерные и в форме

[[id, Open,High,Low,Close], [id, Open,High,Low,Close], ...]

Код F# находится в библиотеке и не может работать со списками C# (я не могу получить значения второго измерения списка в F#). Преобразование всего списка каждый раз, когда выполняется операция F#, слишком дорого. Значения также не могут быть сохранены в списке F#, потому что C# не может их обработать.

Предлагаемые решения:

  1. либо сохранение списка F# в C#, просто для целей хранения, поскольку библиотека не может хранить значения вместе со списком C#, содержащим те же значения, преобразуя части списка по мере необходимости. Основная проблема заключается в том, что файлы могут иметь размер несколько ГБ.

  2. чтение значений, которые необходимы непосредственно из файла в 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# без копирования.

Другие вопросы по тегам