从Haskell中的字符串中过滤出格式[n] [英] Filter out the format [n] from a string in Haskell

查看:84
本文介绍了从Haskell中的字符串中过滤出格式[n]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Haskell比较陌生,我试图从字符串中返回 [n] 格式的引用数。



例如 let x =blah blah [1] blah blah [1] blah blah [2]应该返回 3 ,因为函数会看到这个函数中有三个引用。由于 n 可以是任意数字,因此我无法与 [n] 进行匹配。我已经尝试了诸如 filter([_])之类的东西,但没有运气。

解决方案你可以很容易地用标准的Haskell实现你的目标。这种任务的通用名称是解析,但至少对于这种简单的语法来说,在字符串头上大部分是模式匹配。非常容易,因为Haskell字符串只是字符列表!



首先,考虑您想要的签名。

  extractBracketNums :: String  - > [整数] 

似乎是一个好主意。如果您只想对它们进行计数,那么结果类型也可以是单个 Int ,但是如果您实际输出了您保留的数字列表这个函数通常更有用,而且以后用 length 获得计数是微不足道的。

现在,为了实现这个我们需要三种情况:

  extractBracketNums= [] 

这只是基本情况,确保当字符串被完全消耗时,我们做的任何递归都会安全地终止。

  extractBracketNums('[':r)= ... 

这是一个有趣的例子:我们发现了一个左括号,它可能是一个数字的开始!



在实际执行此案例之前,我们需要再考虑一个:

  extractBracketNums(_:r)= extractBracketNums 

这意味着:a子字符串)不以开头括号开始的字符串对我们来说是不感兴趣的,所以只需放弃任何这样的字符。



现在有趣的案例:我们需要检查在支架再次关闭之前,在左括号之后出现一个数字,并且只有一个数字。所以,我们需要从剩下的字符串的开头尝试分割一个数字。这可以用 span 功能。其签名是(a-> Bool) - > [a] - > ([a],[a]),所以对于我们(Char-> Bool) - >字符串 - > (字符串,字符串)。它在字符上使用谓词,它应该确定一个字符是否可能是数字字符串的一部分。模块 Data.Char 具有确切的功能可用。

  extractBracketNums('[':r)= case span isNumber r of 
.. 。

现在我们需要决定我们是否真的找到了一个数字,而没有别的。如果我们在开始时没有找到数字,那么 span 将立即失败,即给出一个空字符串作为其第一个结果。 / p>

  extractBracketNums('[':r)= case span isNumber r of 
([],_) - > extractBracketNums r

即在这种情况下,我忘记了左括号,因为它不包含(只)一个数字。如果我们在它后面找到一个数字而不是紧随其后的括号(我们将在最后覆盖这个数字),但是如果我们在分割数字后面直接找到一个右括号,我们可以取这个数字,将它从字符串转换为 Integer ,并将其添加到尚未找到的任何其他数字中。

 (num,']':r') - > read num:extractBracketNums r'

现在完成大小写(确实找到了一些数字,它):这也意味着我们会简单地忘记左括号。

 (_,_) - > extractBracketNums r 

所以,一起:

  import Data.Char(isNumber)

extractBracketNums :: String - > [整数]
extractBracketNums= []
extractBracketNums('[':r)= case span isNumber r of
([],_) - > extractBracketNums r
(num,']':r') - > read num:extractBracketNums r'
(_,_) - > extractBracketNums r
extractBracketNums(_:r)= extractBracketNums r


Hey guys I'm relatively new to Haskell and I'm trying to return the number of references of the format [n] from a string.

For example let x = "blah blah [1] blah blah [1] blah blah [2]" should return 3 since the function would see that there are three references in this function. I'm having trouble trying to match against [n] since n can be any number. I have tried things such as filter([_]) but had no luck.

解决方案

You can quite easily achieve your goal with standard Haskell alone. The general name for this kind of task is parsing, but at least for such simple grammars that amounts mostly pattern matching on string-heads. Very easy because Haskell strings are just lists of characters!

First, think about what signature you want.

extractBracketNums :: String -> [Integer]

seems a good idea. If you only want to count them, the result type could as well be a single Int, but if you actually output the list of numbers you keep the function more generally useful, and it's trivial to obtain the count afterwards with length.

Now, to implement this we need three cases:

extractBracketNums "" = []

this is just the base case, ensuring that any recursion we do will safely terminate when the string has been fully consumed. Nothing in the string means, no bracketed numbers either!

extractBracketNums ('[':r) = ...

This is the interesting case: we've found an opening bracket, it might be the beginning of a number!

Before actually implementing that case, we need to consider one more:

extractBracketNums (_:r) = extractBracketNums

This means: a (sub-) string that doesn't begin with an opening bracket is uninteresting for us, so just discard any such character.

Now for the interesting case: we need to check that after the opening bracket comes a number, and only a number, before the bracket is closed again. So, we need to try to split off a number from the beginning of the remaining string. This can be done quite well with the span function. Its signature is (a->Bool) -> [a] -> ([a],[a]), so for us (Char->Bool) -> String -> (String,String). It takes a predicate on characters, which should determine whether a character is possibly part of a number-string. The module Data.Char has that exact function available.

extractBracketNums ('[':r) = case span isNumber r of
    ...

so now we need to decide if we really found a number, and nothing else. If we didn't find a number right at the beginning, then span will immediately fail, i.e. give an empty string as its first result.

extractBracketNums ('[':r) = case span isNumber r of
                              ([],_) -> extractBracketNums r

i.e., in this case I just forget about the opening bracket since it doesn't contain (only) a number. Same plan if we do find a number but not a closing bracket immediately after it (we'll cover that one in the end) but if we do find a closing bracket directly after the split off number, we can take that number, convert it from string to Integer, prepend it to any possible other numbers yet to be found. And be happy.

                              (num,']':r') -> read num : extractBracketNums r'

Now the completing case (did find some number, but no closing bracket after it): this also means we'll simply forget about the opening bracket.

                              (_,_) -> extractBracketNums r

So, all together:

import Data.Char (isNumber)

extractBracketNums :: String -> [Integer]
extractBracketNums "" = []
extractBracketNums ('[':r) = case span isNumber r of
                              ([],_) -> extractBracketNums r
                              (num,']':r') -> read num : extractBracketNums r'
                              (_,_) -> extractBracketNums r
extractBracketNums (_:r) = extractBracketNums r

这篇关于从Haskell中的字符串中过滤出格式[n]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆