您将如何用 Ruby 和/或 Haskell 编写这个 Clojure 片段?
我正在开发一个 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
I was working on a Rails template and was trying to write a bit of code that allows me to populate a table or multiple columns of ul tags "top-to-bottom" and "left-to-right" across however many columns I specify. I'm just getting the hang of Ruby so I couldn't figure this out. I'm also curious about an idiomatic Haskell version for this useful snippet. Improvements to Clojure version appreciated:
(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)))))
With this bit of code I can then do the following:
(table (range 10) :cols 3)
Printed out this would look like so:
0 1 2
3 4 5
6 7 8
9
And the trickier one:
(table (range 10) :cols 3 :direction 'down)
Looks like so:
0 4 8
1 5 9
2 6
3 7
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我可能会使用 Hackage 中的 Data.List.Split 包在 Haskell 中编写类似的内容:
其中一些,例如
Direction
类型和transpose< /code> 技巧,源自 jkramer 的答案。我不会在 Haskell 中使用关键字参数来实现类似的东西(它实际上没有这样的东西,但你可以使用 Edward Kmett 的答案中的记录来模拟它们),但我把这些参数放在第一位,因为它对于部分应用程序更有用(
defaultTable = 表水平 1
)。 splitEvery 函数只是将列表分成适当大小的列表;其余的代码应该很简单。table
函数返回列表的列表;为了获取字符串,showTable
函数会插入制表符和换行符。 (intercalate
函数连接一个列表列表,将它们与给定列表分开。它类似于 Perl/Python/Ruby 的join
,仅适用于列表而不仅仅是字符串。)I would probably write something like this in Haskell, using the
Data.List.Split
package from Hackage:Some of this, like the
Direction
type and thetranspose
trick, was derived from jkramer's answer. I wouldn't use keyword arguments for something like this in Haskell (it doesn't really have such things, but you can emulate them using records as in Edward Kmett's answer), but I put those arguments first because it's more useful with partial application (defaultTable = table Horizontal 1
). ThesplitEvery
function just chunks a list into lists of the appropriate size; the rest of the code should be straightforward. Thetable
function returns a list of lists; to get a string, theshowTable
function inserts tabs and newlines. (Theintercalate
function concatenates a list of lists, separating them with the given list. It's analogous to Perl/Python/Ruby'sjoin
, only for lists instead of just strings.)我无法阅读 clojure 代码(我从未使用过该语言),但根据示例,以下是我在 Ruby 中执行此操作的方法。
I can't read the clojure code (I've never used the language), but based on the examples, here's how I'd do it in Ruby.
这是我在 Haskell 中快速破解的东西。我确信它有问题并且可以优化,但它是从以下开始的:
输出:
Here is something I quickly hacked in Haskell. I'm sure it's buggy and can be optimized, but it's something to start with:
Output:
我的红宝石解决方案
用法和输出:
My ruby solution
Usage and output:
切片和压缩提供了一个简单的 Ruby 解决方案:
Slicing and zipping gives a straightforward Ruby solution:
这为我们提供了原始查询的相当惯用的近似值,并带有可选参数:
我将中间结果保留为数组形式,正如您所表明的那样,您计划将它们格式化为表或 ul 标记。
This gives us a fairly idiomatic approximation of your original query complete with optional arguments:
I left the intermediate results in array form as you had indicated that you them planned to format them as a table or ul tags.