递归函数

发布于 2024-10-27 16:20:27 字数 249 浏览 2 评论 0原文

我在练习中遇到问题,我应该定义一个函数,该函数将整数、字符和字符串作为输入,并返回将字符放入字符串中整数指定的位置的结果,例如,给出 3'a'"haskell" 到该函数应生成 "hasakell"

putinto :: Int -> Char -> String -> String
putinto

I am having trouble with an exercise where I should define a function which takes as input an integer, a character and a string and returns the result of putting the character in the string at the position specified by the integer, for example, giving 3, 'a' and "haskell" to the function should result in "hasakell".

putinto :: Int -> Char -> String -> String
putinto

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

摇划花蜜的午后 2024-11-03 16:20:27

这样想:有一个列表,其中第一个元素称为“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"

不过,您仍然需要关心错误检查(如果给定位置为负数或大于列表长度怎么办?)。

Think about it this way: having a list where the first element is called 'x' and the rest of the list is called 'xs' (in Haskell, this would be written as (x:xs)), you either prepend your given value to the list of the position is 0. Otherwise you call yourself recursively on the remained of the list (and decrease the poisition).

putinto :: Int -> a -> [a] -> [a]
putinto 0 value list   = value : list
putinto n value (x:xs) = x : putinto (n-1) value xs

In case it looks odd, the (x:xs) is actually a "deconstructed" list. The x represents the first element of the list, xs (the 's' means 'plural', so it's the plural of 'x') is the rest of the list.

So calling it with a zero will actually prepend the given value, as in

putinto 0 'a' "haskell"  -- yields 'ahaskell'

Calling it with two will be:

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"

You still need to care about error checking (what if the given position is negative, or larger than the list length?) though.

红焚 2024-11-03 16:20:27
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# 中可以解决问题

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;

this wil do the trick in C#

小嗲 2024-11-03 16:20:27

在为 Haskell 中涉及列表的问题编写显式递归解决方案之前,值得检查一下是否可以使用 PreludeData.List。在这种情况下 splitAt 可以提供帮助:

splitAt 3 "haskell"
("has","kell")

因此,您的问题可以通过拆分、consing 和附加轻松解决:

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

Before writing an explicitly recursive solution to a problem involving lists in Haskell, it's worth checking to see if the same task can be accomplished using the list functions in the Prelude or Data.List. In this case splitAt can help:

splitAt 3 "haskell"
("has","kell")

Thus your problem is easily solved by splitting, consing and appending:

putInto :: Int -> Char -> String -> String
putInto n c xs = let (ys,zs) = splitAt n xs in ys ++ (c:zs)

Just for fun, the above can also be written in a point-free style using the applicative instance for (-> r):

putInto :: Int -> Char -> String -> String
putInto n c = ((++) . fst <*> (c:) . snd) . splitAt n
会发光的星星闪亮亮i 2024-11-03 16:20:27

我认为这应该很容易阅读。我列举了几行来解释:

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

I think this should be fairly easy to read. I enumerated the lines for explanation:

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

What goes on here? The first line is the type signature. The second line checks if you wish to set the character at the front (ie. index 0).

The third and fourth line is for when we wish to insert it later than the 0'th index. The third line checks if the list we want to insert into is empty, in which case we just return the list containing only a.

In the fourth line we know that the first index of our string will still be the first, so we just recurse on the tail, decreasing n as needed along the way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文