我正在研究一个Rails模板,并试图写一些代码,允许我填充一个表或多列ul标签“从上到下”和“从左到右”,但是我指定的许多列.我只是得到了
Ruby的悬念,所以我无法想出这一点.我也很好奇这个有用的代码段的惯用Haskell版本. Clojure版本的改进赞赏:
(defn table [xs & {:keys [cols direction] :or {cols 1 direction 'right}}] (into [] (condp = direction 'down (let [c (count xs) q (int (/ c cols)) n (if (> (mod c q) 0) (inc q) q)] (apply map vector (partition n n (repeat nil) xs))) 'right (map vec (partition cols cols (repeat nil) xs)))))
使用这一段代码,我可以执行以下操作:
(table (range 10) :cols 3)
打印出来会像这样:
0 1 2 3 4 5 6 7 8 9
和更棘手的一个:
(table (range 10) :cols 3 :direction 'down)
看起来像这样:
0 4 8 1 5 9 2 6 3 7
解决方法
我可能会在Haskell中使用来自Hackage的Data.List.Split包写这样的东西:
import Data.List (intercalate,transpose) import Data.List.Split (splitEvery) data Direction = Horizontal | Vertical deriving (Eq,Read,Show) table :: Direction -> Int -> [a] -> [[a]] table Horizontal cols xs = splitEvery cols xs table Vertical cols xs = let (q,r) = length xs `divMod` cols q' = if r == 0 then q else q+1 in transpose $table Horizontal q' xs showTable :: Show a => [[a]] -> String showTable = intercalate "\n" . map (intercalate "\t" . map show) main :: IO () main = mapM_ putStrLn [ showTable $table Horizontal 3 [0..9],"---",showTable $table Vertical 3 [0..9] ]
其中一些,像方向类型和转置技巧,源于jkramer的答案.我不会在Haskell中使用这样的关键字参数(它并不是真的有这样的东西,但是可以使用Edward Kmett的回答中的记录来模拟它们),但是我先把这些参数放在第一位,因为它对部分应用程序更有用(defaultTable =表水平1). splitEvery函数只是将列表分成适当大小的列表;其余的代码应该很简单.表函数返回列表列表;要获取字符串,showTable函数插入标签和换行符. (插入函数连接列表列表,将它们与给定的列表分开,它类似于Perl / Python / Ruby的连接,仅用于列表而不是字符串.)