从XML缓慢导入并自动生成代码

Codey McCodeface

我一直在与Haskell玩,并编写一些代码来解析DICOM医学图像。代码在这里我想创建一个将接受ByteString并返回名称的函数。因此,某个ByteString(实际上是从ByteString中获取的两个Int64)将返回PatientName或StudyDate。其中有成千上万个,它们都包含在XML文件中。因此,为了创建函数,我将解析XML文件并生成所需的函数,然后使用以下命令将其输出到文件中

writeTagNameFromElemGroup :: FilePath -> [(String,String,String,String)] -> IO()
writeTagNameFromElemGroup fp tups = init >> Prelude.appendFile fp ( Prelude.drop 0 tags )
    where init = Prelude.appendFile fp "\ntagNameFromElem :: Element -> Group -> String\ntagNameFromElem e g\n"
      tags = LS.concat $ Prelude.map (\tup -> "    | " ++ (writeTup tup) ++ "\n") filTups
      hexInt x = show . readHex $ x
      filTups = LS.filter (\(w,x,y,z) -> Prelude.length w == 4 && Prelude.length x ==4 ) tups

这将在Tags.hs中创建所需的功能。

tagNameFromElem :: Int64 -> Int64 -> String
tagNameFromElem e g
    | e == 8 && g == 1 = "LengthToEnd"
    | e == 8 && g == 5 = "SpecificCharacterSet"
    | e == 8 && g == 6 = "LanguageCodeSequence"
    | e == 8 && g == 8 = "ImageType"
    | e == 8 && g == 16 = "RecognitionCode"
    | e == 8 && g == 18 = "InstanceCreationDate"
    | e == 8 && g == 19 = "InstanceCreationTime"
    | e == 8 && g == 20 = "InstanceCreatorUID"
    | e == 8 && g == 22 = "SOPClassUID"
    | e == 8 && g == 24 = "SOPInstanceUID"
    | e == 8 && g == 26 = "RelatedGeneralSOPClassUID"
    | e == 8 && g == 27 = "OriginalSpecializedSOPClassUID"
    ..... > 2000 more

每隔一段时间就有一个特殊情况

    | e == 1000 && mod (g -5) 10 == 0 = "ShiftTableTriplet"

这使我不仅仅使用地图。

现在,这种方法可以工作,但是要花很长时间(超过一分钟)来加载整个过程,这使我认为我没有做到这一点。为了重现,我建议克隆存储库并加载Tags.hs。

SSCE

writeFunc :: (Num x, Show x) => FilePath -> [x] -> IO()
writeFunc fp xs  = init >> Prelude.appendFile fp ( maps ) >> Prelude.appendFile fp "|  otherwise = 0 "
    where init = Prelude.appendFile fp "mapVal :: Int -> Int \nmapVal x\n    "
          maps = concat $ Prelude.map (\x -> "| x == " ++ show x ++ " = " ++ show (x +1 ) ++ "\n    ") xs

使用很长的列表〜几千个值,然后尝试导入结果文件

艾丽尔·莫亚·塞奎拉(Ariel D.Moya Sequeira)

该答案基于问题的评论中bheklilr的建议。代码生成取决于您。

我查看了您的代码,发现仅存在其中两个值e规定了特殊条件ge == 28e == 1000因此,最好在单独的函数中处理它们。请选择比以下名称更好的名称。

e28 :: Map Int64 String
e28 = fromList [ (0, "CodeLabel"), (2, "NumberOfTables"), ... ]

e1000 :: Map Int64 String
e1000 :: fromList [ (0, "EscapeTriplet"), (1, "RunLengthTriplet"), ... ]

先前地图的键来自特殊情况的谓词:mod (g - key) 10 == 0

这里的情况e == 1010也很特殊,因为它不依赖g它始终是“ ZonalMap”,因此将在以后处理。

现在,只需使用g创建其余的地图

e40 :: Map Int64 String
e40 = fromList [ (2, "SamplesPerPixel"), (3, "SamplesPerPixelUsed"), ... ]

e84 :: Map Int64 String
e84 = fromList [ ... ]

...

从常规es(即不是28、1000或1010的)创建一个映射到其对应的映射:

regularE :: Map Int64 (Map Int64 String)
regularE e = fromList [ (40, e40), (84, e84), ... ]

总结一下:

import Control.Monad

tagNameFromElem :: Int64 -> Int64 -> Maybe String
tagNameFromElem   28 g = lookup e28 (mod g 10)
tagNameFromElem 1000 g = lookup e1000 (mod g 10)
tagNameFromElem 1010 _ = Just "ZonalMap"
tagNameFromElem    e g = lookup regularE e >>= (`lookup` g)

lookup函数来自Data.Map,以防万一需要限定条件。使用会Maybe处理以下情况:映射到e或未g映射到有效标签名的情况,而不是映射到硬编码的“未找到”字符串的情况。

请注意,我尚未测试此代码。我现在不在家

如果需要,请尝试IntMap代替MapInt在这种情况下,您需要使用Regular ,但是这对本项目可能是好的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章