我在练习时遇到问题,我应该定义一个函数,该函数将整数,字符和字符串作为输入,并返回将字符放入字符串中由整数指定的位置的结果,例如,将3
,'a'
和"haskell"
提供给该函数应该会产生"hasakell"
。
putinto :: Int -> Char -> String -> String
putinto
答案 0 :(得分:6)
以这种方式思考:有一个列表,其中第一个元素称为'x',列表的其余部分称为'xs'(在Haskell中,这将被写为(x:xs)
),你要么将您给定的值前置到该位置列表为0.否则,您将自行调用列表的剩余部分(并减少该值)。
putinto :: Int -> a -> [a] -> [a]
putinto 0 value list = value : list
putinto n value (x:xs) = x : putinto (n-1) value xs
如果它看起来很奇怪,(x:xs)
实际上是一个“解构”列表。 x
表示列表的第一个元素,xs
('s'表示'复数',因此它是'x'的复数')是列表的其余部分。
所以用零调用它实际上会预先给定给定的值,如
putinto 0 'a' "haskell" -- yields 'ahaskell'
用两个调用它将是:
putinto 2 'a' "haskell"
-- same as 'h' : putinto 1 'a' "askell"
-- same as 'h' : 'a' : putinto 0 'a' "skell"
-- same as 'h' : 'a' : 'a' : "skell"
-- same as "haaskell"
你仍然需要关心错误检查(如果给定的位置是负数,或者大于列表长度怎么办?)。
答案 1 :(得分:3)
int j = 3;
char a = 'a';
string x = "haskell";
string part1 = x.Substring(0, j);
string part2 = x.Substring(j);
string result = part1 + a + part2;
这将在C#
中发挥作用答案 2 :(得分:3)
在针对涉及Haskell中的列表的问题编写显式递归解决方案之前,值得检查是否可以使用Prelude
或Data.List
中的列表函数完成相同的任务。在这种情况下,splitAt
可以提供帮助:
splitAt 3 "haskell"
("has","kell")
因此,您可以通过拆分,删除和追加来轻松解决问题:
putInto :: Int -> Char -> String -> String
putInto n c xs = let (ys,zs) = splitAt n xs in ys ++ (c:zs)
为了好玩,以上也可以使用(-> r)
的应用实例以无点样式编写:
putInto :: Int -> Char -> String -> String
putInto n c = ((++) . fst <*> (c:) . snd) . splitAt n
答案 3 :(得分:0)
我认为这应该很容易阅读。我列举了解释的行:
1. putInto :: Int -> Char -> String -> String
2. putInto 0 a xs = a:xs
3. putInto _ a [] = [a]
4. putInto n a (x:xs) = x : putInto (n-1) a xs
这里发生了什么?第一行是类型签名。第二行检查您是否希望在前面设置字符(即索引0)。
第三行和第四行用于我们希望在第0个索引之后插入它的时间。第三行检查我们要插入的列表是否为空,在这种情况下,我们只返回仅包含a
的列表。
在第四行中,我们知道字符串的第一个索引仍然是第一个,因此我们只是在尾部递归,在此过程中根据需要减少n
。