我有以下代码,它应该将excel列类型转换为相应的数字。例如AA到27和AB到28:
import Data.Char (ord)
import Data.List (foldl1')
columnToNumber :: String -> Int
columnToNumber s = foldl1' (\acc (i, v) -> acc + 26 ^ i * v) (values s)
where values s = zip (reverse [0..(length s)]) ((\c -> ord c - 64) <$> s)
这个想法是采取字符串&#34; AA&#34;将其转换为相应的数字
["A", "A"] -> [1, 1]
并用基座拉链,从右到左依次为26 ^ 0,26 ^ 1,26 ^ 2,等等。
zip [1, 0] [1, 1] -> [(1, 1), (0, 1)]
这样折叠的结果将是
26^1 * 1 + 26^0 * 1 = 27
不幸的是,我收到了以下错误,我不确定原因:
ExcelSheetColumn.hs:7:34:
Couldn't match expected type ‘Int’
with actual type ‘(Integer, Int)’
In the pattern: (i, v)
In the first argument of ‘foldl1'’, namely
‘(\ acc (i, v) -> acc + 26 ^ i * v)’
In the expression:
foldl1' (\ acc (i, v) -> acc + 26 ^ i * v) (values s)
ExcelSheetColumn.hs:7:63:
Couldn't match type ‘(Int, Int)’ with ‘Int’
Expected type: [Int]
Actual type: [(Int, Int)]
In the second argument of ‘foldl1'’, namely ‘(values s)’
In the expression:
foldl1' (\ acc (i, v) -> acc + 26 ^ i * v) (values s)
有人可以帮助我吗?
答案 0 :(得分:6)
要让它进行编译,您实际上只需将foldl1'
切换为foldl'
并添加开始累加器:
import Data.Char (ord)
import Data.List (foldl')
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s)]) ((\c -> ord c - 64) <$> s)
如果您添加了建议Free_D
(从length s - 1
开始):
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s -1)]) ((\c -> ord c - 64) <$> s)
你得到了预期的结果:
λ> columnToNumber "AA"
27
λ> columnToNumber "AB"
28
我不知道你是否真的需要这个但是嘿,为什么不呢:
您可能不喜欢的是columnToNumber "A1"
是11
- 为了解决这个问题,您需要使用不同于字母的数字:
columnToNumber :: String -> Int
columnToNumber s = foldl' (\acc (i, v) -> acc + 26 ^ i * v) 0 (values s)
where values s = zip (reverse [0..(length s -1)]) (parse <$> s)
parse c
| c >= '0' && c <= '9' = ord c - ord '0'
| otherwise = ord c - 64
答案 1 :(得分:2)
看一下// ... stuff
else if ( distanceX < 0 ) {
$div.css({
'left': e.clientX,
'top': e.clientY - distanceY,
'width': (1 - distanceX),
'height': distanceY
});
}
else if ( distanceY < 0 ) {
$div.css({
'left': e.clientX - distanceX,
'top': e.clientY,
'width': distanceX,
'height': (1 - distanceY)
});
}
的定义,它必须采取两种相同类型的东西并产生类似的东西
foldl1'
但是*Main Data.List> :t foldl1'
foldl1' :: (a -> a -> a) -> [a] -> a
就是你想要的:
foldl
基本上就是这样:
*Main Data.List> :t foldl
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b