Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 使用char或int拆分字符串/列表_Haskell - Fatal编程技术网

Haskell 使用char或int拆分字符串/列表

Haskell 使用char或int拆分字符串/列表,haskell,Haskell,我试图在Haskell中创建一个函数,将字符串拆分为某个字符,并将列表拆分为某个数字 为了做到这一点,splitAt函数正是我需要的数字,但我不能用这个函数给出一个字符 例如 给予 这正是我需要的元组左侧的5。 但是现在我想用一个char和一个字符串来实现这一点。但是对于第二个参数,splitAt只接受和int。我想要 splitAt 'c' "abcde" 导致 ("abc", "de") 我在寻找一个方向的东西 splitAt

我试图在Haskell中创建一个函数,将字符串拆分为某个字符,并将列表拆分为某个数字

为了做到这一点,splitAt函数正是我需要的数字,但我不能用这个函数给出一个字符

例如

给予

这正是我需要的元组左侧的5。 但是现在我想用一个
char
和一个字符串来实现这一点。但是对于第二个参数,
splitAt
只接受和
int
。我想要

splitAt 'c' "abcde"
导致

("abc", "de")
我在寻找一个方向的东西

splitAt (findIndex 'c' "abcde") "abcde"
但是函数
findIndex
返回的类型可能是Int,
splitAt
需要一个
Int
。然后我尝试了以下方法

splitAt (head (findIndices (== 'c') "abcde")) "abcde"
("ab","cde")
这是一个可能的解决方案,但它返回以下内容

splitAt (head (findIndices (== 'c') "abcde")) "abcde"
("ab","cde")
c在元组的错误一侧。您可以将
succ
添加到c中,但是如果字符是Z,结果会是什么呢

有没有一个简单的方法来修改以使

splitAt (findIndex 'c' "abcde") "abcde"

工作?

您可以使用
findIndex
,只需打开
可能
并添加一个:

import Data.List

splitAfter :: (a-> Bool) -> [a] -> ([a],[a])
splitAfter this xs = case findIndex this xs of
    Nothing -> (xs,[])
    Just n -> splitAt (n+1) xs
例如,给予

*Main> splitAfter (=='c') "abcde"
("abc","de")
*Main> splitAfter' (==5) [1..10]
([1,2,3,4,5],[6,7,8,9,10])
可能是一种方便的数据类型,用于以易于恢复的方式对故障进行编码。甚至还有一个函数
maybe::b->(a->b)->maybe a->b
使用默认值和一个函数分别处理这两种情况:

splitAfter' :: (a-> Bool) -> [a] -> ([a],[a])
splitAfter' this xs = maybe (xs,[]) 
                  (\n -> splitAt (n+1) xs) 
                  (findIndex this xs)
这同样有效。比如说

*Main> splitAfter (=='c') "abcde"
("abc","de")
*Main> splitAfter' (==5) [1..10]
([1,2,3,4,5],[6,7,8,9,10])

您可以使用
fromaybe
函数从Maybe获取结果,例如:

splitlist = splitAt (fromMaybe 0 (findIndex 'c' "abcde") "abcde")
fromaybe::a->Maybe a->a

fromMaybe函数接受默认值和Maybe值。如果 可能为空,返回默认值;否则, 返回函数中包含的值。()


默认值设置为0时,如果findIndex返回
Nothing
,则splitAt的结果将是
(“”,list)
,对于相同的情况,但默认值设置为
length list
,则最终结果将是
(list,“”)
给定的
c::Char
s::String
,你可以写一些

splitAt ((1+) $ fromJust $ findIndex (==c) s) s
但是

  • 如果
    c
    未进入
    s
  • 您可以遍历
    s
    两次
  • 一个
    可能
    的替代方案是

    maybe Nothing (\x -> splitAt (1+x) s) (findIndex (==c) s)
    
    您可以设置“其他值”(
    Nothing
    ,在我的示例中)

    您可以将自己的函数编写为

    splitAt' :: Char -> String -> (String, String)
    splitAt' _ [] = ("", "")
    splitAt' c (x:xs) | c == x = ([c], xs)
                      | True   = (x:cs, ys) where (cs, ys) = splitAt' c xs
    

    然后,如果不是
    s
    中的
    (s,“”)
    ,您将得到
    ,这里有一种不同的方法,它不涉及混淆列表索引

    break
    几乎就是你想要的。让我们重复使用它。您希望匹配元素包含在第一个输出列表的末尾,而不是第二个输出列表的开头

    import Control.Arrow ((***))
    
    breakAfter :: (a -> Bool) -> [a] -> ([a], [a])
    breakAfter p xs = map fst *** map fst $ break snd (zip xs $ False : map p xs)
    
    工作原理:

  • 将输入列表转换为成对列表(
    zip
    )。每对的第一个元素取自原始列表。该对中的第二个元素是一个
    Bool
    ,说明列表中的前一个元素是否是我们要查找的元素。这就是为什么我们说
    False:map p xs
    ——如果我们只是说
    map p xs
    ,我们将准确地再现
    break
    的行为。在开始时插入额外的
    False
    ,这一点很重要
  • 重用
    break
    。我们的条件编码在每对的第二个元素中
  • 扔掉所有那些
    Bool
    s。我们不再需要他们了

  • 如果您使用
    ::(a->Bool)->[a]->([a],[a])
    而不是
    splitAt
    ,则不需要
    findIndex
    @SebastianPaaskeTørholm,但您可以在右侧而不是左侧获得
    'c'