如何使用 Applescript 在列表中找到最大值的索引? [英] How do I find the index of the maximum value in the list using Applescript?

查看:39
本文介绍了如何使用 Applescript 在列表中找到最大值的索引?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个int列表如{18,18,18,18,22,21},我想用Applescript来获取这个列表的最大值,并得到最大索引,请教我

I have an int list such as {18, 18, 18, 18, 22, 21}, I want to use Applescript to get the maximum value of this list, and get the maximum index, please teach me

推荐答案

这有两个阶段:

  1. 识别列表中的最大值;
  2. 一旦知道最大值,确定该值在列表中最后一次出现的索引.

我将在下面演示的示例中使用我自己生成的示例列表.但是,您可以简单地将您的列表替换为我的列表,并且所描述的过程也同样有效,并且会产生特定于您输入的结果.

I'll use a sample list I generated myself in the examples I demonstrate below. However, you can simply substitute your list for mine, and the processes described will work just as well, and produce the results specific to your input.

获取列表中最大值的一种快速而肮脏的方法是使用 bash 数字 sort 命令,然后选择最后一项:

A quick-and-dirty way to get the maxium value in the list is to use a bash numeric sort command, and pick the last item:

    set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}

    set text item delimiters to linefeed
    do shell script "sort -n <<<" & quoted form of (L as text) & "| tail -n 1"
    --> 78

但是,本着解决问题的精神,计算机科学家的方法是遍历列表中的项目并执行以下操作:

But, in the spirit of problem solving, the computer scientist's approach would be to iterate through the items in the list and perform these operations:

  • 存储第一项的值.
  • 如果下一个项目的价值更高,则将当前存储的价值替换为我们刚刚评估为价值更高的项目.
  • 如果下一项不是更大的值,则保留当前存储的值.

一旦到达列表末尾,存储的值必须等于列表中的最大值项.此时,我们不知道它在列表中的位置,但我们知道它的值.

Once you reach the end of the list, the stored value must be equal to the greatest value item in the list. At this point, we don't know its position in the list, but we know its value.

这是执行此过程的 AppleScript:

Here's the AppleScript that performs this process:

    set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
    set max to L's first item

    repeat with x in L
        if x > max then set max to x's contents
    end repeat

    return max
    --> 78

2.确定列表中给定项的索引

暂时搁置最大值,问题的后半部分涉及能够确定任何给定项目在有序列表中的位置.

2. Determining the index of a given item in a list

Putting aside the maximum value for now, the second half of the problem involves being able to determine the position of any given item in an ordered list.

最明显的解决方案是,和以前一样,遍历列表中的每一项并执行此操作:

The most obvious solution to this is, as before, iterating through each item in the list and performing this operation:

  • 如果当前项等于目标项,则将其索引附加到为存储匹配索引而保留的列表的末尾.

一旦到达列表末尾,您的匹配索引列表将包含其值等于目标项目值的项目的所有位置;或者匹配索引列表将是一个空列表,表明主列表不包含我们寻找的值.

Once you reach the end of the list, your matched indices list will contain all the positions of the items whose value equal your target item's value; or the matched indices list will be an empty list, indicating that the main list does not contain the value we sought out.

AppleScript 列表中第一项的索引是 1.使用列表的 length 属性获取整个列表中的项数.

The index of the first item in an AppleScript list is 1. Use the length property of a list to obtain the number of items in the whole list.

这是一个基本的 AppleScript:

Here's a basic AppleScript:

    set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
    set matches to {}
    set target to 78

    repeat with i from 1 to L's length
        if item i of L = the target then set end of matches to i
    end repeat

    return the matches
    --> {3, 7, 10}

3.组合过程

将问题的这两半组合起来就像依次运行每一半一样简单,注意使用过程前半部分的结果——最大值——作为列表中要寻找的目标值:

3. The combined process

Combining these two halves of the problem is as simple as running each half in sequence, being mindful to use the result from the first half of the process—the maximum value—as the target value to be sought out in the list:

    set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
    set max to L's first item
    # Get maximum value
    repeat with x in L
        if x > max then set max to x's contents
    end repeat

    set matches to {}
    set target to max
    # Get index of maximum value
    repeat with i from 1 to L's length
        if item i of L = the target then set end of matches to i
    end repeat

    return the matches
    --> {3, 7, 10}

最后,由于您只想要最大索引,这只是matches 列表中的最后一个值,即10,您通过替换return 获得与此行匹配的:

Finally, as you only want the maximum index, this is simply the last value in the matches list, i.e. 10, which you obtain by replacing return the matches with this line:

    return the last item in matches
    --> 10

4.效率提升

概述了每个过程中的基本方法,这些不一定是最快的方法.对于仅包含 10 个项目的列表,效率低下并不是一个值得注意的问题.如果您有一个包含 10,000 个项目的列表,您会希望能够缩短获得结果的时间.

4. Efficiency improvements

Having outlined the basic methods in each process, these aren't necessarily the fastest methods. With lists containing only 10 items, inefficiency is not a noticeable concern. If you had a list of 10,000 items, you would want to be able to reduce the time to get your result.

我认为我的说法是正确的,就算法改进而言,没有明显的方法可以加快第一个过程:检索最大值需要比较每个项目的大小并保留最大的.

I think I'm correct in stating that there's no discernible way to speed up the first process in terms of algorithmic improvements: retrieving the maximum value necessitates comparing every item's magnitude and retaining the largest.

然而,可以加快确定索引的速度,因为我们只需要确定列表中项目的最后次出现.

Determining the index, however, can be sped up given that we only need to determine the last occurrence of an item in the list.

因此,我们可以像以前一样运行该过程,但要进行两个更改:

Therefore, we can run the process as before, but making two changes:

  1. 从列表的末尾而不是开头开始.
  2. 找到第一个匹配项后停止该过程.

脚本如下:

    set L to {4, 24, 78, 32, 1.5, 32, 78, 4, 19, 78}
    set max to L's first item
    # Get maximum value
    repeat with x in L
        if x > max then set max to x's contents
    end repeat

    set target to max
    # Get index of maximum value
    repeat with i from L's length to 1 by -1
        if item i of L = the target then exit repeat
    end repeat

    return i
    --> 10

注意这里的第二个 repeat 循环现在从最高索引向下运行到 1;并且,我们不再需要 matches 列表,因此我们只需在找到匹配项时退出循环,然后查看我们所处的 i 的值.

Note here the second repeat loop now runs backwards from the highest index down to 1; and, we no longer require the matches list, so instead we simply exit the loop when a match is found, and see what value of i we were at.

对这里算法的进一步改进是测试空情况以确定我们是否真的需要遍历列表:空情况是列表不包含我们的值的情况寻找.AppleScript 提供了一种内置方法来检查:

One further improvement to the algorithm here would be to test for the null case to determine whether or not we really need to run through the list at all: the null case is the case where the list doesn't contain the value we seek. AppleScript provides a builtin way to check this:

    if the target is not in L then return 0

此行将紧接在 set target to max 之后,紧接在 repeat with i... 之前.

and this line would sit immediately after set target to max and immediately before repeat with i....

在解决算法本身的效率问题之后,提高效率的另一种方法是解决脚本编写方式的效率问题.这比您现在需要关心的更高级,但是如果我编写脚本供自己使用,我可能会如何实现算法:

Another way to improve efficiency, after addressing efficiency of the algorithms themselves, is to address the efficiency of the way the script is written. This is more advanced than you need to concern yourself with now, but here's how I'd probably implement the algorithms if I were writing the script for my own use:

我将定义一个名为 maximum() 的处理程序,它将列表作为其参数并返回最大值,并且我将像这样实现此处理程序的脚本:

I would define a handler called maximum() that takes a list as its argument and returns the greatest value, and I would implement the scripting of this handler like so:

    on maximum(L as list)
        local L

        if L is {} then return {}
        if L's length = 1 then return L's first item

        script Array
            property x0 : L's first item
            property xN : rest of L
            property fn : maximum(xN)
            property predicate : x0 > fn
        end script

        tell the Array
            if its predicate is true then return its x0
            its fn
        end tell
    end maximum

这使用一种称为脚本对象的东西来处理列表中的项目,这在 AppleScript 中比传统的迭代 repeat 循环要快得多.

This uses something called a script object to process the items of the list, which is much, much quicker in AppleScript than conventional iterative repeat loop.

接下来,我将定义一个名为 lastIndexOf() 的第二个处理程序,它接受一个提供的值和一个列表作为它的两个参数,并返回提供的值出现在给定列表中的最高索引.我的处理程序看起来像这样:

Next, I would define a second handler called lastIndexOf() that takes a supplied value and a list as its two arguments, and returns the highest index at which the supplied value occurs in the given list. My handler would look like this:

    on lastIndexOf(x, L as list)
        local x, L

        if x is not in L then return 0
        if L = {} then return

        script Array
            property x0 : L's last item
            property xN : reverse of rest of reverse of L
            property predicate : x0 ≠ x
        end script

        # For the last match only:
        if Array's predicate is false then return (Array's xN's length) + 1

        # For a match list (comment out line above):
        tell the Array
            if its predicate is false then ¬
                return the lastIndexOf(x, its xN) ¬
                    & (its xN's length) + 1
            return lastIndexOf(x, its xN)
        end tell
    end lastIndexOf

然后,我需要做的就是:

Then, all I need to do to obtain the result is:

    set L to {4, 24, 78, 32, 1.5, 32, 78, 14, 19, 78}
    get the lastIndexOf(maximum(L), L)
    --> 10

但是,不要试图理解我刚刚在这里所做的事情,而是专注于理解 repeat 循环算法.

But, don't try and understand what I've done here just yet, and concentrate on understanding the repeat loop algorithms.

为了完整性和读者可能想知道,如果我忽略了这一点,为什么我没有提供我可以拥有的最佳解决方案,我已经包含了这些更高级的版本.

I've included these more advanced versions for completeness and for readers who may have wondered, had I left this out, why I didn't provide the most optimal solution I could have.

虽然这些高级版本中使用的算法保持不变(看起来不像,但确实如此),但代码的编写方式使这些算法对于大型项目列表非常有效.

Whilst the algorithm used in these advanced versions remains the same (it doesn't look like it, but it is), the way the code is written makes these incredibly efficient for large itemed lists.

但是请注意,我还没有包含任何错误处理,所以如果您要向这些处理程序传递一个包含非数字项的列表,至少一个他们中的一些人会抱怨.

Note, however, I haven't included any error handling, so if you were to pass those handlers a list that contained non-numerical items, at least one of them would complain.

这篇关于如何使用 Applescript 在列表中找到最大值的索引?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆