簡體   English   中英

Haskell,用它的長度壓縮列表的元素

[英]Haskell, zip the element of a list with its length

下一行應該說明它必須如何工作..

[14,2,344,41,5,666] [(14,2),(2,1),(344,3),(5,1),(666,3)]之后[(14,2),(2,1),(344,3),(5,1),(666,3)]

["Zoo","School","Net"]之后的[("Zoo",3),("School",6),("Net",3)]

這是我的代碼到目前為止

zipWithLength :: [a] -> [(a, Int)]
zipWithLength (x:xs) = zipWith (\acc x -> (x, length x):acc) [] xs

我想弄清楚第二行的問題是什么。

如果將數字轉換為字符串(使用show ),則可以對它們應用length

Prelude> let zipWithLength = map (\x -> (x, length (show x)))
Prelude> zipWithLength [14,2,344,41,5,666]
[(14,2),(2,1),(344,3),(41,2),(5,1),(666,3)]

但是,您不能在字符串列表上使用相同的函數:

Prelude> zipWithLength ["Zoo","School","Net"]
[("Zoo",5),("School",8),("Net",5)]

這些數字不是字符串的長度,而是它們的表示形式:

Prelude> show "Zoo"
"\"Zoo\""
Prelude> length (show "Zoo")
5

如評論中所述,其他類型的元素可能會出現類似問題:

Prelude> zipWithLength [(1.0,3),(2.5,3)]
[((1.0,3),7),((2.5,3),7)]
Prelude> show (1.0,3)
"(1.0,3)"
Prelude> length (show (1.0,3))
7

如果你想在列表的每個元素上應用一個函數,那就是map :: (a -> b) -> [a] -> [b] 地圖因而需要一個函數f和一個列表xs ,並生成列表ys ,使得第i個元件ys ,被f施加到第i個元素xs

所以現在唯一的問題是我們想要的映射功能。 我們想要一個元素x ,並返回一個2元組(x, length x) ,我們可以用lambda表達式表達

mapwithlength = map (\x -> (x, length x))

或者我們可以使用ap :: Monad m => m (a -> b) -> ma -> mb

import Control.Monad(ap)

mapwithlength = map (ap (,) length)

問題是這不適用於Int ,因為它們沒有length 我們可以在這里使用show ,但是還有一個額外的問題:如果我們在String上執行show ,我們得到一個字符串文字(這意味着我們得到一個帶引號的字符串,以及某些字符被轉義的地方)。 基於這個問題,我們不希望如此。

我們可以為它定義一個參數化函數:

mapwithlength f = map (ap (,) (length . f))

我們基本上可以將它留給用戶。 如果他們想要使用整數,他們必須調用它:

forintegers = mapwithlength show

對於String s:

forstrings = mapwithlength id

安裝number-length包后,您可以:

module Test where
import           Data.NumberLength

-- use e.g for list of String
withLength :: [[a]] -> [([a], Int)]
withLength = map (\x -> (x, length x))

-- use e.g for list of Int
withLength' :: NumberLength a => [a] -> [(a, Int)]
withLength' = map (\x -> (x, numberLength x))

例子:

>>> withLength ["Zoo", "bear"]
[("Zoo",3),("bear",4)]
>>> withLength' [14, 344]
[(14,2),(344,3)]

正如bli指出的那樣,使用length (show n)計算數字的長度不會轉移到計算字符串的長度,因為show "foo"變為"\\"foo\\"" 由於事物的長度不明顯,您可以使用長度函數對zip函數進行參數化:

zipWithLength :: (a -> Int) -> [a] -> [(a, Int)]
zipWithLength len = map (\x -> (x, len x))

使用示例:

> zipWithLength (length . show) [7,13,666]
[(7,1),(13,2),(666,3)]

> zipWithLength length ["Zoo", "School", "Bear"]
[("Zoo",3),("School",6),("Bear",4)]

> zipWithLength (length . concat) [[[1,2],[3],[4,5,6,7]], [[],[],[6],[6,6]]]
[([[1,2],[3,4],[5,6,7]],7),([[],[],[6],[6,6]],3)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM