将数字列表中的元素转换为字符的最快方法是什么?此挑战是社区中问题的延伸。我决定测试八种方法:三种迭代方法( For 、 For Each和Transform Each )、四种非迭代方法(表操作、表达式、 Words + 表达式和Regex )和一种混合方法( Words + Transform Each )。链接的帖子中考虑了其中五种不涉及正则表达式或表达式的方法。使用Words和Regex的方法有点作弊,因为它们利用了字符串操作的副作用 - 具体来说,任何数据结构都可以转换为字符串并进行相应的解析。我将让读者决定他们是否认为这种方法合法。我知道有些人会对此皱眉!
使用空间填充设计,我研究了四个因素:列表数量、列表元素数量、列表元素数量是否相等以及数字类型:整数或浮点数。该设计位于列表列表 – Experimental Runs.JMP中。原始设计生成的小数值已四舍五入。每次运行进行十次重复。我用于运行实验的代码位于运行列表实验.JSL中,结果位于列表结果列表.JMP 中。使用正则表达式的初步运行速度非常慢,因此被排除在考虑之外。
为了比较方法,我通过运行和复制计算每种方法的排名顺序,以及实验运行中所有复制的运行时间和中值运行时间之间的差异。越小越好。下图表明Transform Each 、表操作和Words方法更优越。虽然实际时间差异很小(值以微秒为单位),但这些方法的排名始终较高且变异性较小。


为了查看四种方法之间是否存在差异,我使用更大的列表重新运行实验( List of strings big – Experimental Runs.JMP和List of strings big results.JMP )。从运行中的中值时间的时间差异来看,随着项目总数的增加, Transform Each和表操作的性能最佳。这是一个幸运的结果,因为Transform Each刚刚在JMP 16中引入,而表操作为仍在使用 JMP 15 的人们提供了一个很好的解决方案。

对于第二个挑战,我要求你转置列表列表。列表的转置列表将输入列表中的所有第一个元素收集到第一个输出列表中,将第二个输入元素收集到第二个输出列表中,依此类推。如果输入有n 个列表,则每个输出列表将有n 个元素。输出列表的数量将等于每个列表中项目数量的最大值。虽然输入列表的数量很容易确定,但输出列表的数量需要计算每个输入列表中的项目。有这个必要吗?它会导致更快的过程吗?
为了回答这个问题并测试具体方法,我进行了另一个空间填充设计。在其中,我研究了三种迭代方法( For 、 For Each和Transform Each ),每种方法使用两种方法:一种在构建输出之前计算输出列表的数量,需要对输入进行两次循环,另一种使用输入上的单个循环。此外,我还研究了表操作的使用。考虑了六种不同的列表元素类型(整数、浮点、1 个字符、8 个字符、15 个字符和可变宽度字符(最大长度 15)以及固定和可变(内部)列表长度。
在最初的编码过程中,我发现从空列表开始并使用Insert Into构建输出列表比使用Repeat或表达式用缺失值预填充输出要快。您可以使用Prebuild 或 Insert.JSL中的代码亲自检查一下。第二个发现与Transform Each和For Each有关。如果您不熟悉这些函数,它们的行为与标准For或While循环略有不同,因为它们允许您迭代列表、矩阵或关联数组,而无需指定它们的大小。这可以使代码更加紧凑和干净。对这两个函数的基本调用的结构是
fnName ({ indValue , ind },容器,主体)
其中fnName是For Each或Transform Each , indValue是索引ind处容器的值, container是矩阵、列表或关联数组, body是代码主体。使用大型容器时必须小心。使用大型数据结构作为容器或indValue将大大减慢执行速度。使用 For Each 和 Transform Each.JSL中给出了这样的示例。在其中,我们计算列表列表中每个列表中的项目数。前两个代码块对应于您可能期望如何编码问题,第一个使用每个子列表作为输入值,第二个为子列表建立索引。将此与第三个块进行比较,其中aList的索引是在循环中显式创建并使用的。根据aList的大小,处理速度可以提高 100 倍或更好。 Transform Each速度更快,允许它返回结果值。块 4 和 5 显示输出数据结构将与用于输入容器的数据结构相同。有一个可选的Output()参数来控制输出数据结构的类型。
用于测试不同转置方法的代码位于Transpose links.JSL中。如上所述,使用空间填充设计来比较不同条件下的输出。与上面的代码不同,每次重复都会创建一个新的数据结构。前三种方法读取输入并在单个块中构建输出。接下来的三个在处理输入之前首先预先确定输出列表的大小。倒数第二个方法使用表操作,最后一个 Transform Each 方法使用其输出值进行结构化。

事实证明,预先确定输出列表的大小比尝试在单个块中执行此操作更快。 Transform Each的不同实现显示了通过使用其输出值获得的速度改进。结果位于Transpose results.JMP中。可以在转置结果 big.JMP中找到比较For Each 、 Transform Each (第二次实现)和表操作的较大列表的实验。结果表明,表操作总体上优于其他两种方法。

回顾一下我们的发现:
- 按时间:变换每个<对于每个<对于
- 如果不涉及列公式,表操作可以非常快。在之前的文章中,我们看到,根据其复杂性,列公式可以将操作减慢到迭代或表达式有利的程度。
我没有得到过去遇到的这个挑战的典型反馈,所以我确信有更好的方法。我很想听听您的意见。下个月寻找新的挑战。