Я хотел бы написать функцию, которая фильтрует последовательность с помощью предиката, но результат также должен ВКЛЮЧАТЬ первый элемент, для которого предикат возвращает false.
Логика была бы примерно такой, если бы в F# было ключевое слово break
let myFilter predicate s =
seq {
for item in s do
yield item
if predicate item then
break
}
Я пробовал комбинации Seq.takeWhile и Seq.skipWhile, что-то вроде этого:
Seq.append
(Seq.takeWhile predicate s)
(Seq.skipWhile predicate s |> Seq.take 1)
... но проблема в том, что первый элемент, который соответствует предикату, теряется между takeWhile и skipWhile
Также обратите внимание, что входная последовательность является ленивой, поэтому любое решение, которое использует последовательность и принимает решения впоследствии, нежизнеспособно.
Любые идеи?
Спасибо!
РЕДАКТИРОВАТЬ: Большое спасибо за все ответы! Я не ожидал, что так много ответов так быстро. Я рассмотрю каждый из них в ближайшее время. Теперь я просто хочу дать немного больше контекста. Рассмотрим следующий ката код, который реализует оболочку:
let cmdProcessor state = function
| "q" -> "Good bye!"
| "h" -> "Help content"
| c -> sprintf "Bad command: '%s'" c
let processUntilQuit =
Seq.takeWhile (fun cmd -> cmd <> "q")
let processor =
processUntilQuit
>> Seq.scan cmdProcessor "Welcome!"
module io =
let consoleLines = seq { while true do yield System.Console.ReadLine () }
let display : string seq -> unit = Seq.iter <| printfn "%s"
io.consoleLines |> processor|> io.display
printf "Press any key to continue..."
System.Console.ReadKey ()|> ignore
Проблема этой реализации в том, что она не печатает "До свидания!" при вводе команды q.
Что я хочу сделать, так это реализовать функцию processUntilQuit так, чтобы она обрабатывала все команды до "q", включая "q".
s
. - person pad   schedule 24.09.2012