简体   繁体   English

在Haskell的列表列表中替换元素

[英]Replacing element in a list of lists in Haskell

I have a list of lists like so: 我有一个像这样的清单清单:

[["BBBBBBBB",
  "BWFFFPFGB", 
  "BWFFFPFGB",
  "BWFFMPFGB",
  "BWFFFPF_B",
  "BWFFFPF6B",
  "BBBBBBB"]]

I've done a little research and have found out how to access individual elements using the !! 我做了一些研究,发现了如何使用!!访问各个元素!! operator. 操作员。 But when it comes to searching for a certain element 'M' I'm not sure how to go about that. 但是,当要搜索某个元素'M'我不确定该怎么做。 My friend said I need to use something like (x:xs):xss on a list, but when I try this in the WinGHCi haskell program I get this. 我的朋友说我需要在列表上使用(x:xs):xss类的东西,但是当我在WinGHCi haskell程序中尝试此操作时,会得到此信息。

Prelude> let list =    [["BBBBBBBB",
  "BWFFFPFGB", 
  "BWFFFPFGB",
  "BWFFMPFGB",
  "BWFFFPF_B",
  "BWFFFPF6B",
  "BBBBBBB"]]


Prelude> head(x:xs):xss
<interactive>:192:2: Not in scope: `x'
<interactive>:192:4: Not in scope: `xs'
<interactive>:192:8: Not in scope: `xss'

I understand that I declare the name as list and not x:xs but even when I declare it as x:xs I still get the errors. 我知道我将名称声明为list而不是x:xs但是即使将其声明为x:xs我仍然会收到错误消息。 I'm probably still a little new to haskell to really understand what to do so I may be going about this way wrong. 我可能对Haskell还是有点陌生​​,可以真正理解该怎么做,所以我可能会出错。

I've looked here Replace individual list elements in Haskell? 我在这里查看了替换Haskell中的单个列表元素? because eventually I want to replace the M with something different but I'm not completely sure how I would implement that. 因为最终我想用不同的东西替换M ,但是我不确定如何实现。

Any help/guidance is appreciated, thanks! 任何帮助/指导表示赞赏,谢谢!

First of all, virtually all "variables" in Haskell are immutable, so there's no "changing a list", there are modified copies. 首先,Haskell中几乎所有“变量”都是不可变的,因此没有“更改列表”,而是经过修改的副本。

Second, you need to find an element by some criteria. 其次,您需要根据一些条件来查找元素。 To do that, you need to traverse a list. 为此,您需要遍历列表。 - This can be done using recursion. -这可以使用递归来完成。 Filtering can be done using a function passed as an argument of your traversing function (this function must take an element and return a boolean value). 可以使用作为遍历函数的参数传递的函数来完成过滤(该函数必须带有一个元素并返回一个布尔值)。

Try to put the above together and make your own function. 尝试将以上内容放在一起并发挥自己的作用。 Start with a type signature, it shows what you want to do: to take a list of Char (it's better to generalize to a generic type) and a function which possibly changes an element and return a modified list: 从类型签名开始,它显示了您要执行的操作:获取Char列表(最好将其泛化为通用类型)和一个可能更改元素并返回修改后列表的函数:

replaceFunc :: (Char -> Char) -> String -> String replaceFunc ::(字符->字符)->字符串->字符串

Also, read http://www.haskell.org/haskellwiki/How_to_work_on_lists , there's a hint there how to apply some function to specific elements only. 另外,请阅读http://www.haskell.org/haskellwiki/How_to_work_on_lists ,这里有一个提示,指出如何仅将某些功能应用于特定元素。

First let's see how to replace a W with M 首先让我们看看如何用M替换W

charWM :: Char -> Char
charWM 'W' = 'M'  -- If you see W, put M.
charWM x  =  x   -- If you see anything else, put it back as is.

You can rewrite that function how you like by adding other letter transformations. 您可以通过添加其他字母转换来以自己喜欢的方式重写该函数。

Now let's make that work over a list. 现在,让我们在列表上进行操作。 There's a great function map :: (a ->b) -> [a] -> [b] that lets you apply a function on every element on a list. 有一个很棒的功能map :: (a ->b) -> [a] -> [b] ,可让您在列表上的每个元素上应用功能。

stringWM :: String -> String
stringWM xs = map charWM xs  -- do charWM to everything in xs.

For example stringWM "QWERTY WILL WIN" = "QMERTY MILL MIN" 例如stringWM "QWERTY WILL WIN" = "QMERTY MILL MIN"

Next we can do that to a list of lists: 接下来,我们可以对列表进行操作:

lolWM :: [String] -> [String]
lolWM xss = map stringWM xss

( String is a type synonym for [Char] .) String[Char]的类型同义词。)
Let's test that out in ghci: 让我们在ghci中测试一下:

*Main> list'
["BBBBBBBB","BWFFFPFGB","BWFFFPFGB","BWFFMPFGB","BWFFFPF_B","BWFFFPF6B","BBBBBBB"]
*Main> lolWM list'
["BBBBBBBB","BMFFFPFGB","BMFFFPFGB","BMFFMPFGB","BMFFFPF_B","BMFFFPF6B","BBBBBBB"]

All good. 都好。

Your example wasn't exactly list' , it was [list'] which has 1 element, so to work on that we'd need to map lolWM . 您的示例并非完全是list' ,而是[list']具有1个元素,因此要进行工作,我们需要map lolWM Often we wouldn't bother writing stringWM or lolWM and go directly to lists of lists of lists, if that's what we needed: 如果我们需要的话,通常我们不会费心编写stringWMlolWM并直接进入列表列表的列表:

lololWM = (map.map.map) charWM

map.map.map means map the map of the map. map.map.map表示地图的地图。 You can allow that to blow your mind a little, or you can just say list of list of list of Char, so map map map - one map per list level. 您可以让您大吃一惊,也可以只说Char列表的列表列表,所以可以使用map map map-每个列表级别一个map。


In the future, maybe you'll want to replace W with Strings instead of characters. 将来,也许您会想用String代替字符替换W

rewriteChar :: Char -> String
rewriteChar 'W' = "--^--"
rewriteChar  x  = [x] -- put x in a list to make it a string

This time, map isn't enough: map rewriteChar "QWERTY WILL WIN" gives 这次,地图还不够: map rewriteChar "QWERTY WILL WIN"

["Q","--^--","E","R","T","Y"," ","--^--","I","L","L"," ","--^--","I","N"]

We could use concat on that to flatten it into a single list, but it's more fun to do 我们可以在其上使用concat将其展平为一个列表,但是这样做更有趣

rewriteString = concatMap rewriteChar

So now rewriteString "QWERTY WILL WIN" give us "Q--^--ERTY --^--ILL --^--IN" . 所以现在rewriteString "QWERTY WILL WIN"给我们"Q--^--ERTY --^--ILL --^--IN"

For more mindblowing things to try, there's "QWERTY WILL WIN" >>= rewriteChar and "Hello Mum" >>= \\x -> [x,x,x] 要尝试更多"QWERTY WILL WIN" >>= rewriteChar事情,请使用"QWERTY WILL WIN" >>= rewriteChar"Hello Mum" >>= \\x -> [x,x,x]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM