2016-03-08 2 views
5

Этот вопрос исходит от человека, который работает над переходом от R к F #. Я полностью признаю, что мой подход здесь может быть неправильным, поэтому я ищу способ F # сделать это. У меня есть ситуация, когда я хочу перебирать набор файлов XML, анализировать их и извлекать несколько значений, чтобы определить, какие из них нуждаются в дальнейшей обработке. Моим естественным наклоном является Карта по массиву данных XML, exampleData в этом случае, разобрать каждый с использованием провайдера типа RawDataProvider и, наконец, создать объект Map для каждого файла, содержащего проанализированный XML, значение статуса из XML и ItemId стоимость.F # тип коллекции для смешанных типов

Оказывается, что тип карты в F # не похож на список в R. Списки в R являются, по существу, хэш-картами, которые могут поддерживать смешанные типы. Похоже, что тип карты в F # не поддерживает сохранение смешанных типов. Я нашел, что это невероятно полезно в моей работе R, и я ищу, что для этого нужно для правой коллекции F #.

Или, я думаю об этом, все неправильно? Это очень естественный способ обработки данных в R, поэтому я ожидаю, что в F # также будет способ сделать это. Предполагается, что я собираюсь провести дальнейший анализ и добавить дополнительные элементы данных в эти коллекции.

Update: Это кажется таким простым вариантом использования, что должно быть идиоматическим способом сделать это в F # без необходимости определить тип записи для каждого шага анализа. Я обновил свой пример, чтобы еще раз иллюстрировать то, что я пытаюсь сделать. Я хочу, чтобы вернуть массив объектов Map, которые я проанализированные:

type RawDataProvider = XmlProvider<"""<product Status="Good" ItemId="123" />""">   

let exampleData = [| """<product Status="Good" ItemId="123" />"""; """<product Status="Bad" ItemId="456" />"""; """<product Status="Good" ItemId="789" />"""|] 

let dataResult = 
      exampleData 
      |> Array.map(fun fileData -> RawDataProvider.Parse(fileData)) 
      |> Array.map(fun xml -> Map.empty.Add("xml", xml).Add("Status", xml.Status).Add("ItemId", xml.ItemId)) 
      |> Array.map(fun elem -> elem.["calc1Value"] = calc1 elem["itemId"]) 
      |> Array.map(fun elem -> elem.["calc2"] = calc2 elem.["ItemId"] elem.["calc1Value"]) 
+0

Не то, о чем вы просили, но я думаю, что 'File.ReadAllLines (file) |> Array.reduce (+)' может быть заменен на 'File.ReadAllText (файл)' – CoderDennis

+0

@CoderDennis спасибо за информацию –

+0

Вы должны используйте тип записи вместо слабо типизированного хеша. –

ответ

4

Это то, что я хотел бы рассмотреть почти идиоматическим здесь - я держу такую ​​же форму, как в вашем примере, чтобы вы могли соответствовать два:

let dataResult = 
    exampleData 
    |> Array.map(fun fileData -> RawDataProvider.Parse(fileData)) 
    |> Array.map(fun xml -> xml, calc1 xml.ItemId) 
    |> Array.map(fun (xml, calcedValue1) -> xml, calcedValue1, calc2 xml.ItemId calcedValue1) 

что XmlProvider действительно дает вам не просто XML разбора, но тот факт, что она порождает сильно типизированных представление XML. Это лучше, чем перенос данных на карту, поскольку это дает вам более надежные гарантии относительно правильности вашей программы. Например, это не позволит вам перепутать itemId и ItemId, как это произошло в вашем фрагменте кода;)

Для значений, которые вы вычисляете в следующих шагах, вы можете использовать кортежи вместо записи. В общем случае записи предпочтительнее кортежей, поскольку они приводят к более читаемому коду, но объединение связанных значений разных типов в специальные агрегаты - это действительно сценарий, в котором используется синтаксис кортежей.

Теперь, я сказал почти идиоматических - Я бы распадаться синтаксический анализ и обработку разобран XMLs на отдельные функции и вычислить как calc1 и calc2 результаты в одной функции вместо сочинения двух Array.maps вроде этого:

let dataResult = 
    parsedData 
    |> Array.map(fun xml -> 
     let calced1 = calc1 xml.ItemId 
     xml, calced1, calc2 xml.ItemId calced1) 

Если вы исходите из фона R, вы можете проверить Deedle на альтернативный подход. Это дает вам рабочий процесс, похожий на R в F #.

Смежные вопросы