保存前按长度过滤文件 haskell
Filter file by length BEFORE saving haskell
有人问过类似的问题,但手头有一份清单:
Filter list items by length in Haskell
我已经知道如何从文件中获取单词列表
getWords path = do contents <- readFile path
return (lines contents)
然后我可以过滤它以获得特定长度的单词,但是...
我想知道是否有一种方法(最好不是无点样式 - 除非必要)按长度过滤文件 before 将其保存为列表单词。
例如,words.txt是每行1个单词的单词文件。
filteredWords <- filter (\x -> length x == 3) *Read words.txt in place*
我不确定我是否完全理解这个问题。它以 "before saving it as a list of words" 的概念为中心,这在惰性语言中似乎具有误导性。在 Haskell 中,正在做
let list1 = someLongList
list2 = filter p list1
in use list2 -- (but do not use list1)
不会导致 list1
完全存储在内存中:相反,不满足 p
的元素将被立即丢弃。
因此,在 "saving" 之前过滤列表的概念没有意义:这是编译器将为您执行的标准优化。
相反,分离 input/output 和过滤是首选方式。另一种方法,即在代码中混合 I/O 和纯计算,通常被认为是一种更糟糕的方法。 Haskell 类型也鼓励第一种更简单的方法。
利用 IO
也是 Functor
的实例这一事实
filteredWords <- fmap (filter (\x -> length x == 3)) $ getWords path
由于您询问了如何不使用 getWords
:您可以使用函数组合运算符 .
。
filteredWords <- fmap (filter (\x -> length x == 3) . lines) $ readFile path
我认为 readFile
在 Prelude
,如果不是那么它会在 System.IO
是的。这是一个使用 pipes
的示例,它避免具体化完整的单词列表。只有指定长度的单词才会保留在内存中:
import Pipes
import qualified Pipes.Prelude as Pipes
import qualified System.IO as IO
filteredWords :: FilePath -> IO [String]
filteredWords path =
IO.withFile path IO.ReadMode (\handle -> Pipes.toListM (
Pipes.fromHandle handle >-> Pipes.filter (\x -> length x == 3) ))
因此,例如,如果您的文件有 1,000,000 个单词,但其中只有 4 个单词的长度为 3,那么此程序只会生成一个长度为 4 的列表。所有其他元素在读取后将立即被丢弃并且没有存储在内存中的一些中间列表中。
有人问过类似的问题,但手头有一份清单: Filter list items by length in Haskell
我已经知道如何从文件中获取单词列表
getWords path = do contents <- readFile path
return (lines contents)
然后我可以过滤它以获得特定长度的单词,但是...
我想知道是否有一种方法(最好不是无点样式 - 除非必要)按长度过滤文件 before 将其保存为列表单词。
例如,words.txt是每行1个单词的单词文件。
filteredWords <- filter (\x -> length x == 3) *Read words.txt in place*
我不确定我是否完全理解这个问题。它以 "before saving it as a list of words" 的概念为中心,这在惰性语言中似乎具有误导性。在 Haskell 中,正在做
let list1 = someLongList
list2 = filter p list1
in use list2 -- (but do not use list1)
不会导致 list1
完全存储在内存中:相反,不满足 p
的元素将被立即丢弃。
因此,在 "saving" 之前过滤列表的概念没有意义:这是编译器将为您执行的标准优化。
相反,分离 input/output 和过滤是首选方式。另一种方法,即在代码中混合 I/O 和纯计算,通常被认为是一种更糟糕的方法。 Haskell 类型也鼓励第一种更简单的方法。
利用 IO
也是 Functor
filteredWords <- fmap (filter (\x -> length x == 3)) $ getWords path
由于您询问了如何不使用 getWords
:您可以使用函数组合运算符 .
。
filteredWords <- fmap (filter (\x -> length x == 3) . lines) $ readFile path
我认为 readFile
在 Prelude
,如果不是那么它会在 System.IO
是的。这是一个使用 pipes
的示例,它避免具体化完整的单词列表。只有指定长度的单词才会保留在内存中:
import Pipes
import qualified Pipes.Prelude as Pipes
import qualified System.IO as IO
filteredWords :: FilePath -> IO [String]
filteredWords path =
IO.withFile path IO.ReadMode (\handle -> Pipes.toListM (
Pipes.fromHandle handle >-> Pipes.filter (\x -> length x == 3) ))
因此,例如,如果您的文件有 1,000,000 个单词,但其中只有 4 个单词的长度为 3,那么此程序只会生成一个长度为 4 的列表。所有其他元素在读取后将立即被丢弃并且没有存储在内存中的一些中间列表中。