简体   繁体   English

使用不同的功能将地图应用于列表的每个元素

[英]Apply map using a different function to each element of the list

I currently have this bit of code: 我目前有这段代码:

function string keys = map (xor 1) (map ord string)

Which takes every element from the string and xor's it with 1. I would like to make the map function more advanced, by replacing 1 with any element from keys. 它从字符串中获取每个元素,然后用1对其进行异或运算。我想通过将键1中的任何元素替换为1来使map函数更高级。

So for example if string == "Test" and keys = [1,3,6,9] I would get: 因此,例如,如果string == "Test"keys = [1,3,6,9]我将得到:

'T' xor 1
'e' xor 3
's' xor 6
't' xor 9

Is there a way to iterate over all element of keys so that I can achieve this? 有没有办法遍历键的所有元素以便我可以实现这一点? I'm pretty new to Haskell and I don't have a good grasp of its concepts. 我对Haskell还是很陌生,对它的概念也不太了解。

My attempt at solving this was: 我解决这个问题的尝试是:

function string keys = map (iterate xor keys) (map ord string)

but I got a few errors and I guess it's because of the iterate function. 但是我遇到了一些错误,我猜这是由于迭代功能造成的。

Any help would be greatly appreciated! 任何帮助将不胜感激!


Just as I posted I noticed that iterate does a completely different thing so at this point I know why it doesn't work but I don't know how to replace it. 就像我发布的那样,我注意到iterate做的事情完全不同,所以在这一点上我知道为什么它不起作用,但是我不知道如何替换它。

You want to associate one element of a list with one element of the other list. 您想要将一个列表的一个元素与另一个列表的一个元素相关联。 This is often called zipping . 这通常称为zipping The zipWith seems to do exactly what you want: zipWith似乎完全zipWith您的要求:

Prelude Data.Bits> zipWith xor [1, 3, 5] [10, 23, 44]
[11,20,41]

It takes an a -> b -> c function, an [a] list and a [b] list and apply the function element wise with corresponding elements from the two lists. 它需要a -> b -> c函数,一个[a]列表和一个[b]列表,并将该功能元素与两个列表中的相应元素一起明智地应用。

It is a generalization of the zip function that produces pairs of element ( zip = zipWith (,) ). 这是zip函数的通用化,它会生成成对的元素( zip = zipWith (,) )。

That's what the ZipList instance of type class Applicative is doing: 这就是类型类ApplicativeZipList实例正在做的事情:

 > getZipList $ xor      . ord <$> ZipList "Test" <*> ZipList [1,3,6,9, 11]
[85,102,117,125]

The get/ZipList s serve as kind of markers to signal our intent to zip, instead of the regular list's cross-product behaviour. get/ZipList用作一种标记,表示我们打算压缩,而不是常规列表的跨产品行为。 We're supposed to pretend--"ignore" them, reading it in our minds instead as 我们应该假装-“忽略”它们,在我们的脑海中阅读它,而不是

-- zipWith   ( xor       . ord )           "Test"             [1,3,6,9, 11]

which is the same as 这与

-- zipWith     xor (map    ord             "Test" )           [1,3,6,9, 11]
-- zipWith ($) (map (xor . ord)            "Test" )           [1,3,6,9, 11]
-- map (uncurry ($)) (zip (map (xor . ord) "Test" )           [1,3,6,9, 11] )
-- map (\(a,b)-> xor (ord a) b) (zip       "Test"             [1,3,6,9, 11] )

<$> is a synonym for fmap which is a synonym for map , and <*> is "apply". <$>fmap的同义词, fmapmap的同义词,而<*>是“ apply”。

Without the ZipList marker, we get 没有ZipList标记,我们得到

 >    [ord] <*> "Test"
[84,101,115,116]

--     ord  <$> "Test"
-- map ord      "Test"

Specifically, your code should be tweaked a little bit into 具体来说,您的代码应进行一些调整

function :: [Char] -> [Int] -> [Int]
-- function string keys = map (iterate xor keys) (map ord string)
function string keys = zipWith ($) (map xor keys) (map ord string)
      -- = getZipList $ (xor <$> ZipList keys) <*> (ord <$> ZipList string)

($) is an application operator, ($) fx = f $ x = fx . ($)是应用程序运算符, ($) fx = f $ x = fx

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

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