移动列表中特定元素的简单函数

2024-05-04

我是 Haskell 的新手,我正在尝试弄清楚如何创建一个函数:

    shift:: Eq a => a -> [a] -> Int -> [a]
    shift x (h:t) z

输入:一个通用列表和一个相同类型的元素 x

前提条件:元素x存在于列表中

Output:

如果 n

如果 n > 0,则将 x 右移 n 直到到达列表的最后一个

如果n == 0,则从列表中删除x(总是谈论x的第一次出现,它可能在列表中显示超过1次)。

请记住,我已经完成了删除功能

    delete :: Eq b => b -> [b] -> [b]

找到所需元素的第一次出现并将其删除。我想我可以在班次内使用删除。任何形式的帮助表示赞赏。

[一些 I/O 示例]

     Main> shift 3 [] 5
     []
     Main> shift 0 [1,2,3,4] 4
     [1,2,3,4]
     Main> shift 3 [1,2,3,4,3,2,1] 3
     [1,2,4,3,2,3,1]
     Main> shift 6 [1,2,3,4,5,6,7,8] 7
     [1,2,3,4,5,7,8,6]
     Main> shift 'k' "skin" 0
     "sin"
     Main> shift '.' "factor.bit." (-2)
     "fact.orbit."
     Main> shift '.' "0000.1111.00" (-10)
     ".00001111.00"
     Main> shift "one" ["one", "two", "three"] (-2)
     ["one","two","three"]
     Main> shift "one" ["one", "two", "three"] 1
     ["two","one","three"]
     Main> shift "three" ["one", "two", "three"] 5
     ["one","two","three"]

正如 @WillemVanOnsem 所建议的,您可能想尝试编写一个将目标元素向右移动一格的函数。即使这个简化的问题也可能非常具有挑战性!

看看是否可以实现直接递归版本。它的结构可能与您的类似delete函数,除非它会swap两个元素,而不是在关键点删除一个元素。 (答案在底部——寻找定义simpleShiftRight.)

完成此操作后,请尝试使用这种替代方法,该方法的优点是更容易推广到解决您的原始问题。

首先,使用delete不是很有帮助,因为delete“忘记”元素原来在哪里。例如,以下两者:

delete '.' "abc.def"
delete '.' "abcde.f"

yield "abcdef",并且尚不清楚如何使用此结果,例如将句点位置向右移动一个位置。

相反,您真正想做的是将字符串分成目标元素之前和之后的部分。也就是说,你想定义一个函数split其工作原理如下:

> split '.' "abc.def"
("abc","def")
> split '.' "abcde.f"
("abcde","f")

有了这个结果,改变周期就变得容易多了。

例如,如果我们想将周期向右移动一位,我们可以首先定义一个函数

pairRight :: ([a], [a]) -> ([a], [a])

其工作原理如下:

> pairRight ("abc","def")
("abcd","ef")
> pairRight ("abcde","f")
("abcdef","")

和一个函数

rejoin :: a -> ([a], [a]) -> [a]

其工作原理如下:

> rejoin '.' ("abcd","ef")
"abcd.ef"
> rejoin '.' ("abcdef","")
"abcdef."

并将它们组合起来:

> rejoin '.' (pairRight (split '.' "abc.def"))
"abcd.ef"
> rejoin '.' (pairRight (split '.' "abcde.f"))
"abcdef."

得到一个将字符向右移动一位的函数。

Now, split可以根据库函数来定义break,像这样:

split :: Eq a => a -> [a] -> ([a], [a])
split x xs = let (a, _:b) = break (==x) xs in (a,b)

能实现一下功能吗pairRight and rejoin?它们不应该太难,但如果你遇到困难,答案就在底部。

您可能还想尝试定义split从头开始而不使用break。这是一个有点棘手的递归函数。如果您从“明显”的方法开始:

split :: Eq a => a -> [a] -> ([a], [a])
split x (y:ys) | x == y    = (..., ys)
               | otherwise = split x ys
split _ [] = error "split: target not found"

你会遇到问题。不清楚如何填写...因为你在递归中丢弃了列表的开头。希望您已经了解到解决此问题的一种方法是引入一个额外的参数来跟踪已处理的列表元素并定义一个函数:

split' :: Eq a => a -> [a] -> [a] -> ([a], [a])
split' x ls (r:rs) = ...

where x是我们要寻找的元素,ls是我们已经处理过的列表左侧的元素集(其中我们没有找到x), and (r:rs)是我们仍在处理的列表的右侧。

如果您需要进一步的提示,这里有一个模板:

split' x ls (r:rs) | x == r    = (..., ...)
                   | otherwise = split' x (...) rs
split' _ _ [] = error "split: target not found"

可以填写一下吗...这里?如果可以的话,您可以定义:

split :: Eq a => a -> [a] -> ([a], [a])
split x xs = split' x [] xs

一旦你有split, pairRight, and rejoin定义后,您应该能够将它们组合成一个函数:

shiftRight :: Eq a => a -> [a] -> [a]

可以将目标元素向右移动一位。

如果你遇到困难,这里有一个完整的定义shiftRight和它的 帮手:

shiftRight :: (Eq a) => a -> [a] -> [a]
shiftRight x xs = rejoin x (pairRight (split x xs))

-- alternative definition of split:
-- split :: Eq a => a -> [a] -> ([a], [a])
-- split x xs = let (a, _:b) = break (==x) xs in (a,b)

split :: Eq a => a -> [a] -> ([a], [a])
split x xs = split' x [] xs

split' :: Eq a => a -> [a] -> [a] -> ([a], [a])
split' x ls (r:rs) | x == r    = (ls, rs)
           | otherwise = split' x (ls ++ [r]) rs
split' _ _ [] = error "split: target not found"

pairRight :: ([a], [a]) -> ([a], [a])
pairRight (ls, r:rs) = (ls ++ [r], rs)

rejoin :: a -> ([a], [a]) -> [a]
rejoin x (ls, rs) = ls ++ [x] ++ rs

在这个版本中,尝试shiftRight不在列表中或已经位于最右边位置的目标将给出错误。您可能想尝试解决这个问题。 (注意split可以返回一个Maybe [a],产生Nothing如果没有找到目标;修改起来也不应该太困难pairRight因此,如果该对已经尽可能向右移动,则它不会执行任何操作。)

如果这对于一个简单的问题来说似乎很麻烦,我想确实如此。在实际代码中,经验丰富的 Haskell 程序员可能会编写直接递归版本:

simpleShiftRight :: (Eq a) => a -> [a] -> [a]
simpleShiftRight x (y:z:rest) | x == y    = z:y:rest
                              | otherwise = y : simpleShiftRight x (z:rest)
simpleShiftRight _ rest                   = rest

或者这个使用break:

simpleShiftRight :: (Eq a) => a -> [a] -> [a]
simpleShiftRight x xs = case break (==x) xs of
  (ls, y:z:rs) -> ls ++ z:y:rs
  _ -> xs

两个版本都很简洁,处理所有极端情况,并且“显然是正确的”。正如前面提到的,缺点是这个版本不太容易推广到您的原始问题。

上面的版本确实很容易概括——你只需要替换pairRight具有更复杂的配对移位功能。例如,定义:

pairRightN :: Int -> ([a],[a]) -> ([a],[a])
pairRightN n (ls, r:rs) | n > 0 = pairRightN (n-1) (ls ++ [r], rs)
pairRightN _ (ls, rs)           = (ls, rs)

允许您处理所有正值n(即,无论有多大,都可以)。进一步将其推广到处理左移也不是太难。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

移动列表中特定元素的简单函数 的相关文章

  • Python-使用元组作为列表索引[重复]

    这个问题在这里已经有答案了 我有一个元组列表 tuples list 1 0 2 3 3 2 2 0 我想访问二维数组的元素a例如 使用其中一些元组 for i in range 3 print a tuples list i 应该输出的值
  • 搜索重写规则

    有什么办法可以浏览或搜索重写规则吗 当我使用像这样的标志时 ddump rule firings or ddump rule rewrites我只是得到了触发的规则的名称以及它引起的重写 但没有得到实际的规则本身 理想情况下 我想通过 GH
  • 将 num 的签名键入 double?

    我才刚刚开始为你学习 Haskell 以获得伟大的好处 并且我在类型类方面遇到了一些麻烦 我想创建一个接受任何数字类型并强制其为双精度的函数 我的第一个想法是定义 numToDouble Num gt Double 但我认为这不起作用 因为
  • 将两个 Int 值相除以获得 Float 的正确方法是什么?

    我想分两份IntHaskell 中的值并获得结果Float 我尝试这样做 foo Int gt Int gt Float foo a b fromRational a b 但 GHC 版本 6 12 1 告诉我 无法将预期类型 Intege
  • Python range() 和 zip() 对象类型

    我了解功能如何range and zip 可以在 for 循环中使用 然而我期望range 输出一个列表 很像seq在 Unix shell 中 如果我运行以下代码 a range 10 print a 输出是range 10 表明它不是一
  • 如何将列表转换为元组列表?

    我想转换 z z a z z a a z to z 2 a 1 z 2 a 2 z 1 我该怎么做 所以 我需要累积以前的值 它的计数器和元组列表 我已创建记录 record acc previous counter tuples 重新定义
  • “Eta减少”并不总是在Haskell中举行?

    我发现我可以说 LANGUAGE RankNTypes f1 forall b b gt b gt forall c c gt c f1 f id f HLint 告诉我我可以在这里做 Eta 减少 但是 f2 forall b b gt
  • C# 如何单击 IList 中的 IWebelement?

    所以我尝试单击 YouTube 上的按钮 但我无法通过 Xpath 找到该按钮 因为按钮太多 所以我尝试将它们保存在 IList 中 现在我想单击列表中的特定按钮 ChromeDriver chrome new ChromeDriver L
  • Haskell 中列表列表的笛卡尔积

    给定一个长度列表的列表x所有子列表的长度都相同y 输出y x长度列表x包含每个子列表中的一项 例子 x 3 y 2 1 2 3 4 5 6 Output 2 3 8不同的输出 1 3 5 1 4 5 1 3 6 1 4 6 2 3 5 2
  • Haskell 中的中缀运算符优先级

    对于以下 Haskell 表达式 返回 a gt gt f 应该读作 返回a gt gt f or 返回 a gt gt f 这里的相关规则是什么 规则始终是函数应用程序的优先级高于任何运算符 因此 return a gt gt f 被解析
  • Backbone Marionette CompositeView 排序列表 - 在添加时呈现额外的模型

    这是小提琴 http jsfiddle net QhQ8D 10 http jsfiddle net QhQ8D 10 代码在下面 制作一个聊天应用程序 需要一个排序的 连接的用户列表 名称上带有比较器的图形集合连接到 CompositeV
  • R:ifelse 中的字符串列表

    我正在寻找与 MySQL 中的 where var in 语句类似的东西 我的代码如下 data lt data frame id 10001 10030 cc1 rep c a b c 10 attach data data new lt
  • 简单 Haskell Monad - 随机数

    我正在尝试扩展代码这个帖子 https stackoverflow com questions 3944170 haskell and state 接受的答案 允许我能够基于以种子作为参数的函数 randomGen 调用 randomGen
  • 两个布尔列表之间的逻辑运算

    我得到了一个奇怪的结果 我尝试应用and or the orpython 中 2 个布尔列表的运算符 事实上 我得到的结果与我的预期完全相反 True False False and True True False gt True True
  • 迭代列表的奇怪速度差异

    我创建了两个重复两个不同值的长列表 在第一个列表中 值交替出现 在第二个列表中 一个值出现在另一个值之前 a1 object object 10 6 a2 a1 2 a1 1 2 然后我迭代它们 不对它们执行任何操作 for in a1 p
  • Haskell 标准库是什么?

    GHC专用库可以称为标准库吗 或者只有 Haskell 2010 报告中的那些才算数 许多 GHC 库可以通过 Haskell 报告中的函数来实现 可能与 C 绑定相结合 但其他语言依赖于 GHC 特定的扩展 因为语言报告中定义的当前 Ha
  • 在 Django 模板中使用 forloop.counter 值作为列表索引

    在我的 Django 1 1 1 应用程序中 我在视图中有一个函数 它向模板返回一系列数字和项目列表列表 例如 data item1 item2 item3 item4 item5 item6 item7 item8 item9 retur
  • 如何在 R 中合并同名列表中的数据框?

    我有一个包含很多数据框的列表 如果它们具有相同的名称 我想合并它们 即合并所有具有相同名称 a 和 b 的数据框 像这样 a lt aaaaa b lt bbbbb c lt ccccc g lt list df1 lt data fram
  • R中的字典数据结构

    在 R 中 我有 例如 gt foo lt list a 1 b 2 c 3 如果我输入foo I get a 1 1 b 1 2 c 1 3 我怎样才能看透foo仅获取 键 列表 在这种情况下 a b c R 列表可以具有命名元素 因此可
  • 检查对以下内容的理解:“变量”与“变量” “价值”、“功能”与“抽象”

    这个问题是后续问题this one https stackoverflow com questions 25327705 is function a sort of variable 25329157 25329157在学习 Haskell

随机推荐

  • Xamarin 中 QR 扫描后的处理对话框

    我在Xamarin应用程序中使用QR码扫描仪 当它扫描QR码时 它会执行一些操作 大约需要一分钟 而在执行操作时 我想在屏幕上显示一个加载对话框 但是 它没有显示在屏幕上 并且在应用程序的其他地方 它运行得很好 Code var expec
  • 如何配置Android AccessibilityService

    我正在研究AndroidAccessibilityService想要查看所有可能发生的事件类型 手势和关键事件 我能够收到所有public void onAccessibilityEvent final AccessibilityEvent
  • Fabric.js 如何在不拉伸文本的情况下水平调整 IText 大小

    我在父 Group 对象中有这个 IText 对象 当我选择组并水平 以及垂直 调整其大小时 IText 也会调整大小 这使得文本拉伸并且看起来很糟糕 现在我想做的是将 IText 中心本身 保持其纵横比 放在组内 我怎样才能做到这一点 我
  • 关于合并排序代码中的组合步骤的困惑

    我有一个关于数组上的合并排序如何工作的问题 我理解 划分 步骤 它将输入数组划分为 1 长度的元素 然而 当谈到 合并 部分 组合步骤 时 我感到困惑 例如 给定输入 3 5 1 8 2 除法过程将产生 5 个元素 3 5 1 8 2 我只
  • 在 Swift 3 中从 UUID 获取数据

    我用 Objective C 编写了以下代码 我试图在 Swift 3 中使用它 一些等效函数似乎在 Swift 3 中不可用 下面的代码是 Objective C 中的代码 NSUUID vendorIdentifier UIDevice
  • 适用于 Angular 2+ 的具有多个日期选择的日历

    我需要显示一个日历并让用户选择多个日期 例如2017 年 1 月 2 日 2017 年 1 月 3 日 2017 年 1 月 4 日 也就是说 不是一个范围 而是多个日期 在 Angular 1 x 中 我使用了gm datepickerM
  • PHP - Paypal API 表单和安全性 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我在我的电子商务应用程序上使用标准 php paypal 表单进行付款 我注意到只有 firebug 的人可以在通过 立即付款 按钮发
  • 如何切换到新数据库

    我想将我的 django 项目部署到生产环境 并将其与一个新的空数据库关联 我做了如下操作 创建一个新的空数据库 更新了settings py并将数据库名称指向新的数据库名称 删除了我的应用程序下的migrations文件夹 运行 pyth
  • 在sql server中透视固定的多列表

    我有一个需要为报告服务进行旋转的表格 DateCreated Rands Units Average Price Success Unique Users 2013 08 26 0 0 0 0 0 2013 08 27 0 0 0 0 0
  • Microsoft Graph API 中的一个或多个属性包含无效值

    我想在 Azure Active Directory B2C 上创建用户 我按照给定链接中的每个步骤进行操作Here https learn microsoft com en us azure active directory b2c ac
  • 如何重定向到外部404页面Python Flask

    我正在尝试将 404 重定向到外部 URL 如下所示 app route 404 def http error handler error return flask redirect http www exemple com 404 404
  • 将 vbCrLf 应用于文本框的内容

    我在 Excel vba 项目中有一个用户窗体 在设计时它是空的 在表单初始化事件中 我有以下代码 Private Sub UserForm Initialize txtSQL value SELECT MyName ColY vbCrLf
  • 在 gridLayout 中从右向左放置项目

    我有一个GridLayout在我的其中一个布局中 我想从右到左放置项目 这意味着我希望将单元格 1 1 放在布局的右上角 我已经测试了这些代码GridView so far 1 android gravity right and andro
  • 如何在 php 数组中添加条件?

    这是数组 anArray array theFirstItem gt a first item if True conditionalItem gt it may appear base on the condition theLastIt
  • 未初始化成员的警告在 C++11 上消失

    我编译这个简单的程序 include
  • 使用回溯(而不是 DFS)背后的直觉

    我正在解决单词搜索 https leetcode com problems word search description LeetCode com 上的问题 给定一个 2D 板和一个单词 查找该单词是否存在于网格中 该单词可以由顺序相邻单
  • 使用 swift 在 WKWebView 上显示活动指示器

    我正在处理以下代码 并尝试在页面加载时在视图中显示活动指示器 我尝试实施WKNavigationDelegate方法 但我失败了 因为没有任何显示 对于如何解决这个问题 有任何的建议吗 我没有设置 SupportWebView 视图dele
  • 在哪里存储字符串值?在 strings.xml 中还是在常量类中?

    在android中 我们可以将字符串值存储在strings xml文件中或某些常量类中作为静态最终变量 在某些情况下是否有理由选择一个而不是另一个 简而言之 代码中使用的值 始终使用常量类 优点 代码保持集成 并且您的包可以在其他项目 上下
  • CPU缓存:两个地址之间的距离是否需要小于8字节才能具有缓存优势?

    这似乎是一个奇怪的问题 假设缓存行的大小为 64 字节 此外 假设 L1 L2 L3 具有相同的缓存行大小 this https stackoverflow com a 15333156 8385554帖子说英特尔酷睿 i7 就是这种情况
  • 移动列表中特定元素的简单函数

    我是 Haskell 的新手 我正在尝试弄清楚如何创建一个函数 shift Eq a gt a gt a gt Int gt a shift x h t z 输入 一个通用列表和一个相同类型的元素 x 前提条件 元素x存在于列表中 Outp