我有ByteString
,其中包含Float
s的表示形式。每个Float
由ByteString
中的3个字节表示。
我需要对Float
值进行一些处理,因此我希望对Vector
Float
个值执行处理。最好的方法是什么?
我有一个函数toFloat :: [Word8] -> Float
,它将ByteString
的3个字节转换为Float。因此,我考虑以3个字节为步长迭代ByteString
,并将Float
的每个步骤转换为vector
。
我查看了Vector
的库函数,但我找不到任何适合此目的的函数。 Data.Vector.Storable.ByteString.byteStringToVector
看起来很有希望,但它会转换每个字节(而不是每3个字节)并且不会让我控制ByteString
到Float
的转换应该如何发生。
答案 0 :(得分:3)
只需使用Data.Vector.generate
:
V.generate (BS.length bs `div` 3) $ \i ->
myToFloat (bs BS.! 3*i) (bs BS.! 3*i+1) (bs BS.! 3*i+2)
它会一次性分配矢量,并填充它。 Data.ByteString.!
是O(1),所以这非常有效。
答案 1 :(得分:2)
尝试使用
splitAt :: Int -> ByteString -> (ByteString, ByteString)
将ByteString拆分为两个:正好是3个字符之一,另一个包含输入的其余部分。您可以使用它来实现递归函数,该函数将为您提供长度为3的所有组(类似于Data.List.Split.chunksOf
),然后您可以在每个组上使用unpack
来获取[Word8]
您需要。通过toFloat
函数传递,然后使用Vector.fromList
转换为矢量。
有许多步骤看起来可能它们可能很昂贵,但我认为编译器可能足够智能融合它们中的一些,如unpack / fromList对。并且分割ByteString是O(1),因此该部分不像它看起来那么昂贵。这似乎应该像任何一种方法一样合适。