脚本中的迭代

这个演示说明了如何使用 For 函数进行迭代。到目前为止,我们已经使用带有日志的脚本编辑器来测试脚本并观察结果。但现在我们想使用调试器来查看结果。我打开一个脚本编辑器窗口,首先输入“Names Default to Here”。然后输入布尔值。我现在不添加空格。我实际上要把所有内容都输入到一行中,然后让自动重新格式化功能帮我清理。所以我先输入一个分号,然后输入 For,左括号,a 等于分号,b 等于分号,i 等于逗号——这样我就初始化了三个变量。然后我将输入测试,即 i 小于逗号,然后我将更新 b 和 i。所以 b 会更新—— b + 等于。所以这是就地赋值函数,add to 函数,它会覆盖 b 的当前值并将其增加一个分号,因为我要更新两个值,然后是 i++,++ 再次作为后置增量运算符,它会就地添加到 i 中。然后是一个逗号,这个简单循环的主体就是 Show 函数。我只显示 a、逗号、b、逗号——然后我会使用运算符调用乘法函数——所以 a 乘以 b。然后我会关闭所有括号,添加分号,然后右键单击并重新格式化。现在有一件事——嗯,这里有两件事要注意——第一是 JMP 为我添加了一些额外的分号。它看到我在第一个参数中将函数粘合在一起。它看到我在第三个参数中将函数粘合在一起。所以它添加了这些分号。它们不会造成损害。实际上,我可能会从脚本中删除这些,因为除非我要添加或合并更多函数,否则它们没有必要。我可能会做的另一件事是重新排列这些代码,使每个参数都有自己的一行。但我希望当我们进入调试器时,这与课程 PDF 中的内容相匹配。因此,除了删除那些分号外,我将保留 JMP 重新格式化后的代码。我们可以通过几种方式启动调试器。您可以转到“编辑”菜单,那里有一个“调试脚本”选项。您可以看到键盘快捷键是 Ctrl+Shift+R。您可以点击“脚本编辑器”窗口中的“调试”工具栏按钮。或者,您可以右键单击并选择“调试脚本”。由于这是我向您展示的最后一个方法,我将继续使用该方法。因此,这个调试器是 JMP 的第二个实例。原始的 JMP 实例暂时被挂起。因此,如果有任何类型的交互,例如脚本所需的对话框,调试器窗口将暂停,直到您执行该操作。完成后,控制权将返回给调试器。调试完成后,只需关闭它即可。您可以使用右上角的“X”或工具栏上的“停止”按钮。这将返回到 JMP 的原始实例。首先,我将按原样运行此循环,而不设置任何断点。这里有两个按钮。一个是“运行”,另一个是“不带断点运行”。由于我现在没有任何断点,所以这两个按钮的作用相同。如果我有现在想使用的断点,我会使用最左边的这个按钮。点击它。它会告诉我程序执行已终止,除非我重新启动,我稍后会重新启动。唯一的选择是关闭调试器。但在重新启动之前,我想转到显示脚本的面板下方的“局部变量”选项卡。默认命名空间是“Here”,也就是我在第 1 行调用的命名空间。您可以看到,在脚本运行结束时,a 的值为 ,b 的值为 ,i 的值为 。现在我想使用调试器查看迭代每一步中 a、b 和 i 的值。因此,我将点击“重新启动”按钮。我想在第 1 行添加一个断点。为此,我点击行号右侧的 。您可以根据需要设置任意数量的断点。在这个简单的脚本中,我们实际上只需要一个断点。这意味着我们将评估第 1 行并设置“Here”命名空间。然后在 for 循环中,我们将评估初始化参数。我们将评估测试。我们将评估 for 循环的主体,也就是 Show 函数。然后我们将暂停,并在“局部变量”选项卡中看到这些值。让我切换回上面那个。然后当我再次点击“运行”时,我们将更新、执行测试、运行主体、暂停并查看这些值。我们会一直这样做,直到测试失败并退出循环。所以我不想选择任何内容。我将使用左侧的“运行”按钮。同样,我不想在没有断点的情况下运行它。所以我将运行它。你可以看到,在评估之后,我们在第 行停止了。a、b 和 i 的值分别为 和 。要运行迭代的下一步,我再次点击“运行”按钮。现在我看到 a、b 和 i 的值分别为 和 。我可以再运行一次。我们达到了 a、b 和 i 的最终值。我收到程序执行已终止的消息。如果我想做其他事情,我可以重新启动。我可以点击“停止”按钮。或者我可以使用右上角的 X 来关闭。然后我继续点击“停止”按钮。这样,控制权就回到了我最初的 JMP 会话。现在假设我们已经测量了某种正在生产的化合物的固化时间。在生产过程中,每次运行都会进行五次采样,并确定每个样品的固化时间。我们想要查看每个样品的固化时间分布。因此,在“课程日志”部分,我将点击“固化时间数据”。我们建议在编写脚本时,以交互方式尝试各种操作,以确保你正在尝试的操作是可行的。因此,我想要固化时间的直方图。我将举一个简单的例子来开始。我将转到“分析”菜单,选择“分布”。然后将“固化时间”设置为 Y 轴。再次强调,记住这里的角色是 Y。然后点击“确定”。看到这个结果,我觉得这太棒了。这正是我想要的所有五个固化时间分布的结果。这就是我想要使用的平台。我整理了一个可以重新创建此报告的脚本小模板。我回到主窗口并打开它。这个脚本包含分发平台启动、Y 角色以及以“固化时间”为字符串的列函数,它将重新创建该报告。我将基于此模板编写一个循环。我将关闭“固化时间”窗口,然后导航回我的脚本编辑器并清除内容,这样我就可以使用同一个窗口了。同样,我将以“名称默认为此处”作为脚本的开头。和之前一样,我将使用 JMP 自动重新格式化来清理脚本。我的 for 循环将以参数 c 开始。我将为 c 赋值。这是我要初始化的唯一变量。我将输入一个逗号。测试结果将是 c 小于等于列数。提醒一下,如果您正在处理大型数据表,最佳做法可能是在循环外部计算列数,将结果存储在变量中,然后将与 c 进行比较的值赋给该变量。在本例中,列数是五列,因为我们从第二列开始。一共是五列。所以我并不担心每次都要重新计算。但最佳做法是将其取出。我会在其后输入一个逗号。更新参数将是 c 和后置增量运算符、两个加号、另一个逗号,然后我将在括号中输入 Distribution,y,再次打开括号,输入列,然后将 c(计数器)放入括号中。现在我要用箭头指向上方,以确保所有括号都匹配。实际上,如果我这里缺少一个右括号,然后尝试重新格式化,就会收到一条消息,提示缺少某些内容。所以重新格式化实际上是一种简单的调试方法。我只需输入分号,然后使用“重新格式化脚本”按钮,最后运行脚本即可。使用这个脚本,我会得到一个单独的窗口,用于显示每个固化时间值的观察值,因为我启动了分布——如果我们回到“脚本编辑器”窗口——我会在迭代的每个步骤再次启动分布平台。但如果您熟悉分布——我将返回“分析”菜单,选择“分布”,然后将所有五个固化时间值放入 Y 轴中。如果您熟悉分布,您就会知道您可以在同一个窗口中获得所有这些值。在日志中,有一个预先编写的脚本,用于循环构建包含所有列名的 Y 角色,并在同一窗口中生成包含所有五个分布的相同报告。在开始之前,我需要关闭所有这些报告窗口。我将打开菜单栏,在“窗口”下,选择“关闭所有报告”。然后找到日志。点击脚本“固化时间分布”。我们将在调试器中执行此操作。我将在调试器环境中(而不是在脚本编辑器窗口中)讨论每一步发生的情况。我将右键单击并选择“调试脚本”。再次提醒,我们可以通过多种方式启动调试器。我想在每行添加一个断点,以查看迭代每一步发生的情况,就像我们在之前的简单示例中所做的那样。我还想在 c 变量和 yCol 变量上添加一个监视点。我要进入“监视”选项卡。点击绿色加号添加监视。这样我就可以查看脚本中的特定变量了。现在,我的变量不多。但是,如果你的脚本很大,包含很多变量,而在调试时只需要关注几个变量,那么使用“监视”选项卡是一个不错的选择。我要点击绿色加号添加监视。输入变量 c,然后点击“确定”。然后,我还想添加对变量 yCol 的监视,然后点击“确定”。在开始运行之前,我想先简单介绍一下整个脚本中发生的事情。然后,我们将在运行调试器的过程中看到这些。第一行代码创建了一个名为 yCol 的变量。 yCol 将存储分销平台的 Y 分析角色,后面跟着空括号,因为我的循环将通过在 Y 角色后的括号中添加列名来构建此表达式。我用 Expr 引用它,因为如果您只是尝试输入 yCol 并在其后用括号赋值 y,则会出错,因为 JMP 无法将其识别为已定义的变量。它无法将其识别为函数。所以我只想获取存储在 yCol 中的文字值,而无需 JMP 尝试对其进行求值。这就是 line 的作用。以下几行是我的 for 循环,我们从列开始,迭代直到用完所有列。同样,在生产级脚本中,尤其是在数据表较大的情况下,我们希望在循环外部计算列数,并将其放入变量中。然后,for 循环的主体只是将 c 列(即第一轮中的列)添加到存储在 yCol 中的表达式中。插入函数不会尝试计算其第一个参数。因此,我无需对 yCol 变量进行任何特殊操作。它只需查看该变量,然后执行相应的操作,在本例中,将列添加到 y 后面的括号中。Show 函数仅用于演示,以便我们查看每一步的具体操作。如果我没有使用调试器,这段代码会显示在日志中。因此,我关注的是这些值,这相当于使用 Show 函数。我们进行更新。我们进行测试,假设 c 仍然小于或等于列数,我们将下一列插入 yCol。然后,一旦循环完成,换句话说,我们用完了所有列,我们就得到了最后一行代码,我将从内到外地详细解释这一点。我们想使用插入函数来修改分布表达式。我们使用“插入”而不是“插入”,因为分布是 JMP 内置的平台启动项。用户实际上无法修改分布本身。我们可以修改使用分布的表达式。所以我们使用插入函数。然后我们将分布函数封装在 Expr 函数中,这样 JMP 就不会尝试计算分布函数的值。如果我启动——我只想强调这一点——如果我只运行这行代码,JMP 会说,嘿,你没有给我 Y 角色所需的参数。所以它会给我一个分布平台启动。然后用户会输入他们的列,但我们实际上不会——这会违背我们脚本的目的,对吧?这是第一个参数。第二个参数——如果我只输入 yCol 作为第二个参数,JMP 会尝试计算它的值。它会看到——你会看到我们完成循环后它会是什么样子。但它只会看到带括号的大写 Y 和一堆列名。而 JMP 不知道该如何处理这些。它无法将其识别为变量名或函数。因此,Name Expr 使我能够查看存储的内容和 yCol,而无需尝试计算它的值。存储在 yCol 中的未求值表达式将被放入分布后面的括号中。因为一旦我这样做了,所有列中带有 Y 角色的分布仍然被引用,所以我们将整个表达式封装在 Eval 中。当我们回到 JMP 的常规实例时,我们可以继续进行,并进一步细分。所以我有我的观察点。目前,变量未定义。这就是显示的值。让我们运行到第一个断点。在更新之前的第一次运行之后,c 存储的是……的值。现在 yCol 不再是一个带有空括号的 Y,而是列固化时间。记住,在我的小模板中,您可以在背景中看到——我无法导航到它,因为调试器处于活动状态——但这就是仅为一列生成该分布的原因。所以我将再次运行下一次迭代。现在 c 等于,并且 y 分析角色启动了两个固化时间列。我将再次运行。现在我们有三个了。我可以继续这样做。您可以在后台日志中看到,由于“Show”函数的作用,这些结果才会显示出来。我会继续这样做,直到退出循环。所有五个固化时间列都已存储——这在常规 JMP 会话的日志中更容易看到——但现在它们都存储在 yCol 中。因此,程序执行已终止。我将继续,并在调试器中点击“停止”。这样,最后一行就被评估了。我在同一个窗口中显示了包含所有五个直方图的固化时间分布。现在,让我们再次回到“脚本编辑器”窗口,简要讨论一下这一行,因为我认为思考如何从内到外构建表达式非常重要。因此,我将运行该程序并创建一些错误,以确保我们清楚地了解我们为什么要这样写。因此,我将注释掉预先编写的这一行。回到我在调试器实例中描述的情况,我将输入单词 Insert。对于脚本编写新手来说,可能需要反复试验才能确定何时使用 Insert,何时使用 Insert Into。但同样,在这种情况下,我正在尝试——我需要启动一个具有特定分析角色或分析角色中特定列的平台。但我无法修改平台。我只能修改用户创建的变量。这些被称为 L 值。让我们试试这个。我将为该启动输入 Distribution,打开括号,关闭括号,输入一个逗号,然后尝试插入 yCol。同样,我是从一个简单的角度来考虑这个问题的,我想要的是 yCol 中存储的内容以及 distribution 后的括号。让我们看看运行这一行时会发生什么。[错误提示] 我收到一个错误,名称未解析。在访问或评估所有列的 Y 时出现 Y。所以如果我忽略它,那只是意味着 JMP 尝试过评估它。但它无法评估。所以我们得到了一个错误。所以这没有完成。所以再次强调,当我们需要检索存储的表达式或引用的表达式而不对其进行评估时,我们使用的函数是 Name Expr。所以我要包装——哎呀——左括号。我要将 yCol 包装在 Name Expr 中。你可以测试一下。那么会发生什么。如果我刚刚运行 yCol,你会看到我们刚刚得到的错误。如果我运行 Name Expr yCol,那么你可以在日志中看到——哎呀,我正在尝试调整它的大小。你可以在日志中看到 JMP 并没有给我一个错误。它只是返回那个引用的表达式。所以现在当我尝试运行行哦,好吧,这次,问题是——所以 JMP 这次没有遇到 yCol 变量的问题。但现在它看到的分布没有所需的值。所以我不希望 JMP 启动这个平台。我会取消它。我想将分布函数封装在 Expr 中,这样 JMP 就不会尝试对其进行求值。同样,您可以突出显示它并运行它来测试它,好的,这不会造成任何问题。现在,当我运行它时,如果我查看日志,就会看到我运行的那行代码。这是结果,包含 Y 角色的分布以及其中包含的所有列。所以,最后一部分,正如您在行中看到的那样,是封装整个代码——这只是一种方法——但将整行代码封装在 Eval 函数中。然后我运行它。会有一个分布窗口,其中包含所有分布报告。所以我只是想介绍一下我在开发过程中犯的一些错误,因为我认为这有助于人们理解我们为什么以这种方式编写这些东西。现在我要提到的另一件事是,我们通常建议——当我做第一个固化时间分布时,如果你还记得的话,我进入“分析”>“分布”,在“Y”角色中输入“固化时间”,然后点击“确定”。我们通常建议你直接使用JMP为你编写的脚本,并以此为基础,在本例中,就是编写这个循环。我没有对分布这样做的唯一原因是,我使用那个Y分析角色的语法是旧语法。如果我转到“分布”旁边的红色三角形,并选择“将脚本保存到脚本窗口”,新语法会分别指定每一列是连续分布还是名义分布。因此,与旧语法相比,这个循环中的脚本编写量略多一些。旧语法运行良好。但我可能会建议使用这个新语法。它只是一个稍微复杂一点的循环。但对于大多数平台来说,使用JMP为我们编写的脚本就足够了。我要关闭这个脚本窗口了。我们将再看一个交互式操作的示例。这次,我将截取该脚本。不过,我的循环是预先写好的。假设我想查看所有五个固化时间值的控制图。因此,我将通过转到“分析”菜单开始交互式操作。在“质量和过程”下,我将选择“控制图生成器”。我想将“日期”设置为子组角色,将“固化时间”设置为 Y 角色。控制图生成器会自动生成固化时间的单次测量值和移动极差图。这就是我的起点。我将点击“完成”以隐藏控制面板。然后,我将转到“控制图生成器”旁边的红色三角形,并将“将脚本保存到脚本窗口”。因此,这个“脚本编辑器”窗口——这个“脚本编辑器”窗口——现在包含将重新创建该结果的控制图生成器。现在,为了使其与我预先编写的脚本匹配,我将删除设置大小的行。当然,您不必这样做。我只是为了演示而简化了这个过程。我们看到的是,控制图生成器在平台启动时显示。然后我们有一些选项。我们使用布尔值隐藏了控制面板,我们没有显示功能。然后是变量角色。变量角色有一个子组。对于所有固化时间值,它都是相同的。然后它有一个 Y 角色,代表固化时间,在本例中是“固化时间”。所以我们实际上需要做的是建立三个部分。我们需要用固化时间列建立 Y 分析角色,通过添加来建立变量部分——一旦我们在 Y 角色中有了所有固化时间列——就把它添加到这里。然后将变量部分放入控制图生成器启动项中。让我们回到日志,点击“固化时间控制图”。再次强调,Y 分析角色由三个部分组成。这就像我们所做的一样——这些穿过的线就像我们在分布图中看到的一样。我只是对变量使用了不同的命名约定。然后我们要构建变量部分。所以我只使用“插入”函数。我有一些带有“Day”子组的变量,这些变量对于所有固化时间值都是相同的。但我不想让 JMP 尝试计算单词变量。否则会出错。所以我将使用 Expr。然后,就像该脚本中的分布一样,我将检索存储在 yExpr 中的列列表,并将其添加到变量部分中。然后,在这个脚本中,我实际上是在构建不包含变量部分的控制图生成器的基本模板,并将其存储在变量 ccExpr 中。最后,我将添加变量行。同样,如果我们在后台查看该代码,该变量行将被添加到控制图生成器启动中。在本例中,我对这两个变量都使用了 Name Expr,因为它们是我已经定义的带引号的表达式。我将结果存储在它自己的变量中,而不是将这个插入函数包装在 eval 中。然后我在脚本中使用 cc,它将评估构建的表达式。让我们继续,将其带入调试器。因此,我将右键单击并选择“调试”。我将导航到“监视”选项卡。我想从其他脚本中删除当前的监视变量,因此我只需点击按钮即可删除所有监视。然后,我将为此脚本中的四个变量添加四个监视。因此,我将点击绿色加号。首先,我输入 yExpr,然后点击“确定”。然后,我将再次点击绿色加号,并添加 varExpr。我将其大写并不重要,但我只想与脚本中此处文本的内容保持一致。因此,我将点击“确定”。我想添加 ccExpr。点击“确定”。最后,我想添加 cc,然后点击“确定”。我要设置三个断点,因为我想在这里的三个不同位置停止。第一个断点位于 yExpr 行上,这样我就能查看迭代每一步发生的情况。下一个断点位于 yExpr 行上,所以我们暂停一下,以便查看 varExpr 中存储的内容。最后,我们将在 yExpr 行上设置一个断点,以查看 cc 中存储的内容。一旦我们关闭它,它就会被求值。我将使用“Step Over”按钮来执行调试器。我点击它。然后 yExpr 行会被求值,我们进入循环。如果我们查看下面的“Watch”选项卡,您可以看到存储的内容和当前的 yExpr。然后,当我再次点击“Step Over”时,我们会转到第一个断点。当我第三次点击“Step Over”时,您可以看到 yExpr 中包含了“Column Cure Time”。我将再次点击“Step Over”转到该断点。再次点击一次。现在我们已经将“固化时间”插入到 Y 角色中。我会继续这样做,直到 for 循环结束。如果您查看了此代码,您会看到所有五个固化时间列都位于该 Y 角色中。现在,该行将定义 varExpr。现在,这些变量包含子组“日期”,然后是包含所有这些列的 Y 角色。我再次点击“步过”,这将带我们到定义 ccExpr 的位置。您也可以在“监视”选项卡中看到,它只是存储了控制图生成器的启动信息,但缺少了一个重要的部分。然后,我们将所有内容整合在一起。因此,我将再次“步过”。现在,如果您想检查一下,“控制图生成器”、“显示控制面板”等程序都已将存储在 varExpr 中的值添加到其中。我再次点击“步过”。程序执行终止。我点击“停止”。现在,回到我的常规 在 JMP 会话中,您可以看到我已获得固化时间等的单次测量值和移动极差图。在这些示例中,我们将学习如何使用 For 函数、Expr 函数、使用“Insert”命名 Expr 函数,以及如何在这些简单的上下文中使用调试器。我将返回到日志,点击“全部删除”“全部保存”“不保存”而不保存对任何脚本窗口的更改。本次演示到此结束。