Я довольно новичок в F #, но я очарован этим и хочу применить его к некоторым приложениям. В настоящее время у меня есть несколько CSV-файлов, которые являются просто отметкой времени и значениями некоторых датчиков, отметка времени уникальна, но значения столбцов различны.
Например у меня есть два файла CSV
csv1:
timestamp, sensor1
time1, 1.0
csv2:
timestamp, sensor1, sensor2
time2, 2.0, 3.0
Я хочу получить результат
timestamp, sensor1, sensor2
time1, 1.0,
time2, 2.0, 3.0
Интересно, есть ли простой способ сделать это в F #. Спасибо
ОБНОВЛЕНИЕ 1:
Здесь мое текущее решение, которое включает использование LumenWorks.Framework.IO.Csv (https://www.nuget.org/packages/LumenWorksCsvReader) для анализа CSV в Data.DataTable и Deedle (https://www.nuget.org/packages/Deedle) для преобразовать Data.DataTable в Frame и использовать метод SaveCsv для сохранения в CSV-файлы.
open System.IO
open System
open LumenWorks.Framework.IO.Csv
open Deedle
// get list of csv files
let filelist = expression_to_get_list_of_csv_file_path
// func to readCsv from path and return Data.DataTable
let funcReadCSVtoDataTable (path:string) =
use csv = new CachedCsvReader(new StreamReader(path), true)
let tmpdata = new Data.DataTable()
tmpdata.Load(csv)
tmpdata
// map list of file paths to get list of datatable
let allTables = List.map funcReadCSVtoDataTable filelist
// create allData table to iterate over the list
let allData = new Data.DataTable()
List.iter (fun (x:Data.DataTable) -> allData.Merge(x)) allTables
//convert datatable to Deedle Frame and save to csv file
let df = Frame.ReadReader (allData.CreateDataReader())
df.SaveCsv("./final_csv.csv")
Причина использования LumenWorks.Framework.IO.Csv заключается в том, что мне нужно проанализировать несколько тысяч файлов одновременно и в соответствии с этой статьей (https://www.codeproject.com/Articles/11698/A-Portable-and-Efficient-Generic-Parser-for-Flat-F) LumenWorks.Framework.IO.Csv - самый быстрый.
ОБНОВЛЕНИЕ 2: ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ
Благодаря Томасу о решении карты RowsKey (см. Его комментарий ниже) я перевернул его код для случая списка файлов
// get list of csv files
let filelist = expression_to_get_list_of_csv_file_path
// function to merge two Frames
let domerge (df0:Frame<int,string>) (df1:Frame<int,string>) =
df1
|> Frame.mapRowKeys (fun k-> k+df0.Rows.KeyCount)
|> Frame.merge df0
// read filelist to Frame list
let dflist = filelist |> List.map (fun (x:string)-> Frame.ReadCsv x)
// using List.fold to "fold" through the list with dflist.[0] is the intial state
let dffinal = List.tail dflist |> List.fold domerge (List.head dflist)
dffinal.SaveCsv("./final_csv.csv")
Теперь код выглядит «функциональным», однако я получаю небольшое предупреждение от Frame.ReadCsv, что метод не предназначен для F #, но все равно работает.