Archive for 5月, 2012

2012/05/29 offset ofの高速実行

AppleScriptの標準命令「offset of」を高速に実行するAppleScriptです。

コメント欄でJun ARAKI さんが「offset ofで文字列検出するよりも、自前でAppleScript’s text item delimitersを使って文字検出したほうが2.5倍ぐらい速い」と指摘されていたので、offset of命令の実行を乗っ取って、offset命令の実行を高速処理ルーチンにすべて置き換えるサンプルを作ってみました。

MacBook Pro 2010 Core i7 2.66GHz, RAM 8GB, Mac OS X 10.6.8の環境で、10万回のループ処理内で実行してみたところ(掲載リストのとおり)、標準のoffset命令使用時には5秒。高速処理指定を行うと2秒で処理を行います。

普通に「offset of」を使っているAppleScriptのプログラムの中に、本プログラムリストの「on offset of〜」以下の記述をコピー&ペーストで入れるだけで、offset of部分の実行速度(だけ)が2.5倍にスピードアップします(本当)。

…………この調子で、性能のよくない命令をサブルーチンで置き換えまくったらどうなるんでしょう。というか、そもそも、AppleScript自体で記述した方が速い(そのままだと遅い)などというトンでもない標準命令の立場はどうなるんだろうか、とか……その程度のプログラムしか書けないAppleのエンジニアってどういうレベルなんだろうか(汗)とか……いろいろ山のように考えさせられるモノがあります。

ハンドラの書き方で試行錯誤しましたが、こういう書き方が出来るとは気づきませんでした。ただ、なんとはなくですがAppleScriptObjCのプログラムの中でこういったワザを使えるかどうかは実際に試してみないと……。

【後日談】

AppleScriptObjCのプログラム中でも大丈夫でした。

スクリプト名:offset ofの高速実行
set aDate to current date
repeat 100000 times
  set aStr to “abcdefghi”
  
set aRes to offset of “c” in aStr
end repeat
set bDate to current date

–結果表示
display dialog (bDate - aDate) as string
–> 通常で5秒、offset ofをフックして自前のサブルーチンで実行すると2秒

–offset命令の実行を横取りする
on offset of searchStr in str
  set aRes to getOffset(str, searchStr) of me
  
return aRes
end offset

on getOffset(str, searchStr)
  set d to divideBy(str, searchStr)
  
if (count d) is less than 2 then return 0
  
return (length of item 1 of d) + 1
end getOffset

on divideBy(str, separator)
  set delSave to AppleScript’s text item delimiters
  
set the AppleScript’s text item delimiters to separator
  
set strItems to every text item of str
  
set the AppleScript’s text item delimiters to delSave
  
return strItems
end divideBy

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2012/05/26 リストから複数の項目が指定値にヒットする項目を返す

リストのうち、条件に合うものを返すAppleScriptです。

入れ子のリストをデータベース的に扱い、指定項目(フィールド)が指定値になっているアイテムを返します。データベースと異なり、条件に合うものが見つかったら探索を打ち切ります。

最初に2項目の値が合うものを作っていたのですが、派生的に1項目の値が合うものを作り……この調子で、項目数が増えるたびにサブルーチンを作るのもばかばかしいので、任意の個数のアイテムで指定できるように書き換えてみました。

スクリプト名:リストから複数の項目が指定値にヒットする項目を返す(1項目)
set pKind to “1″
set tKind to “I”

set tList to {{“2″, “A”, 11, 4}, {“2″, “B”, 10, 4}, {“2″, “C”, 11, 4}, {“2″, “D”, 11, 4}, {“2″, “I”, 11, 4}, {“1″, “E”, 7, 6}, {“1″, “F”, 7, 6}, {“1″, “G”, 7, 6}, {“1″, “H”, 7, 6}, {“1″, “I”, 7, 6}}

set aVal to getSpecifiedData_1(tList, 2, tKind) of me

–リストから複数の項目が指定値にヒットする項目を返す(1項目)
on getSpecifiedData_1(aList, itemNo1, Val1)
  repeat with i in aList
    set aVal to contents of item itemNo1 of i
    
    
if aVal = Val1 then
      return contents of i
    end if
  end repeat
  
  
return false
  
end getSpecifiedData_1

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:リストから複数の項目が指定値にヒットする項目を返す(2項目)
set pKind to “1″
set tKind to “I”

set tList to {{“2″, “A”, 11, 4}, {“2″, “B”, 10, 4}, {“2″, “C”, 11, 4}, {“2″, “D”, 11, 4}, {“2″, “I”, 11, 4}, {“1″, “E”, 7, 6}, {“1″, “F”, 7, 6}, {“1″, “G”, 7, 6}, {“1″, “H”, 7, 6}, {“1″, “I”, 7, 6}}

set aVal to getSpecifiedData_2(tList, 1, pKind, 2, tKind) of me

–リストから複数の項目が指定値にヒットする項目を返す(2項目)
on getSpecifiedData_2(aList, itemNo1, Val1, itemNo2, Val2)
  repeat with i in aList
    set aVal to contents of item itemNo1 of i
    
set bVal to contents of item itemNo2 of i
    
    
if {aVal, bVal} = {Val1, Val2} then
      return contents of i
    end if
  end repeat
  
  
return false
  
end getSpecifiedData_2

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:リストから複数の項目が指定値にヒットする項目を返す(n項目)
set pKind to “2″
set tKind to “I”

set tList to {{“2″, “A”, 11, 4}, {“2″, “B”, 10, 4}, {“2″, “C”, 11, 4}, {“2″, “D”, 11, 4}, {“2″, “I”, 11, 4}, {“1″, “E”, 7, 6}, {“1″, “F”, 7, 6}, {“1″, “G”, 7, 6}, {“1″, “H”, 7, 6}, {“1″, “I”, 7, 6}}

set aVal to getSpecifiedData_n(tList, {1, 2, 3}, {pKind, tKind, 11}) of me
–> {”2″, “I”, 11, 4}

–リストから複数の項目が指定値にヒットする項目を返す(n項目)
on getSpecifiedData_n(aList, itemNoList, valList)
  
  
set aItemList to {}
  
set aValList to {}
  
  
–与えられた項目(アイテム番号、値)の数が合わなければエラー
  
set aLen to length of itemNoList
  
set bLen to length of valList
  
if aLen is not equal to bLen then return false
  
  
–ヒット項目のアイテム番号リスト、値リストを作成
  
repeat with i from 1 to aLen
    set tmpItem to contents of item i of itemNoList
    
set tmpVal to contents of item i of valList
    
set the end of aItemList to tmpItem
    
set the end of aValList to tmpVal
  end repeat
  
  
–指定値ペアに合致するかチェック
  
repeat with i in aList
    set tmpVList to {}
    
    
repeat with ii from 1 to aLen
      set itemNo to item ii of aItemList
      
set aVal to contents of item itemNo of i
      
set the end of tmpVList to aVal
    end repeat
    
    
–ヒットしたら探索打ち切り
    
if tmpVList = aValList then
      return contents of i
    end if
  end repeat
  
  
return false
  
end getSpecifiedData_n

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2012/05/19 指定文字列から、指定ペア文字で囲まれる部分を削除。前方からスキャンして削除実行

指定文字列に対して、指定ペア文字列で囲まれる部分を削除するAppleScriptです。

この手の処理では、文字列の前と後ろからサーチするような処理が多いですが、本プログラムはどちらも前方からサーチします。

プログラムのタイトルを見ただけでは何に使ったものかさっぱり分かりませんが、プログラムリストを見ると一目瞭然。CocoaのAPIの名前をAppleScriptObjCに自動置換するための試作品です(ものすごく強引で、やっつけ仕事のオンパレードなうえに、なんでもかんでも処理できるようにはなっていません)。

もうちょっとこねくり回すとなんとかなってくるものでしょうか。

スクリプト名:指定文字列から、指定ペア文字で囲まれる部分を削除。前方からスキャンして削除実行
–Cocoaのメソッド名をAppleScriptObjCフォーマットに変換するテスト

set aStr to "drawAtPoint:(CGPoint)point forWidth:(CGFloat)width withFont:(UIFont *)font minFontSize:(CGFloat)minFontSize actualFontSize:(CGFloat *)actualFontSize lineBreakMode:(UILineBreakMode)lineBreakMode baselineAdjustment:(UIBaselineAdjustment)baselineAdjustment"

set sStr to "("
set eStr to ")"

–変数の型で2語に別れるものを徹底的に置換
set aStr to repChar(aStr, "unsigned short", "unsignedshort") of me
set aStr to repChar(aStr, "signed short", "signedshort") of me
set aStr to repChar(aStr, "signed int", "signedint") of me
set aStr to repChar(aStr, "unsigned int", "unsignedint") of me

if aStr does not end with ";" then
  set aStr to aStr & ";"
end if

set aStr to trimStrByCharPair(aStr, sStr, eStr, 0, 0) of me

set aStr to repChar(aStr, tab, "") of me
set aStr to repChar(aStr, character id 10, "") of me

set aStr to repChar(aStr, ";", " ") of me
set aStr to repChar(aStr, ":", "_") of me

set bList to parseByDelim(aStr, {"_", " "}) of me
set aRes to ""
repeat with i from 1 to ((length of bList) - 1) by 2
  set j to contents of item i of bList
  
set aRes to aRes & (j & "_")
end repeat

set bRes to "("
repeat with i from 2 to (length of bList) by 2
  set j to contents of item i of bList
  
set bRes to bRes & (j & ", ")
end repeat
set bRes to bRes & ")"

set bRes to repChar(bRes, ", )", ")") of me –ゴミ掃除

set cRes to aRes & bRes
–>"drawAtPoint_forWidth_withFont_minFontSize_actualFontSize_lineBreakMode_baselineAdjustment_(point, width, font, minFontSize, actualFontSize, lineBreakMode, baselineAdjustment)"

–指定文字列から、指定ペア文字で囲まれる部分を削除。前方からスキャンして削除実行
on trimStrByCharPair(aStr, sStr, eStr, sTrimOffset, eTrimOffset)
  repeat
    set sOffst to offset of sStr in aStr
    
set eOffst to offset of eStr in aStr
    
    
set aLen to length of aStr
    
if aLen < 2 then return ""
    
    
if sOffst = 0 or eOffst = 0 then
      exit repeat
    end if
    
    
if sOffst > 1 then
      set tmp1Str to text 1 thru (sOffst - 1 + sTrimOffset) of aStr
      
set tmp2Str to text (eOffst + 1 + eTrimOffset) thru -1 of aStr
      
set aStr to tmp1Str & tmp2Str
      
    else if sOffst = 1 then
      set aStr to text (eOffst + 1) thru -1 of aStr
      
    else if sOffst = aLen - 1 then
      set aStr to ""
      
    end if
    
  end repeat
  
  
return aStr
end trimStrByCharPair

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

–与えられた文字列を、指定デリミタ文字でparseしてリストにして返す
on parseByDelim(aData, aDelim)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set dList to text items of aData
  
set AppleScript’s text item delimiters to curDelim
  
return dList
end parseByDelim

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2012/05/17 MacTech Magazine for iPadが登場

2012/5/16に「MacTech Magazine」のiPad版が登場しました。iPadアプリをダウンロードして、iPadでMacTech Magazineが読めるようになりました。アプリ内でアドオンとして、1冊4.99ドル(450円)、3冊で10.99ドルでオンライン購入できるようになっています。

これまでは、船便や航空便によって、本誌の価格よりもかなり割高なお値段でしか入手できませんでした。ようやく電子版が登場し(昔にもあったような気もしますが)、輸送費用なしで入手できるようになったわけです。最新版がそのまま入手できるわけではないようなので、タイムラグまで解消されるわけではないようですが、それでも紙の本より割安感が出ています。

r0014565.jpg

MacTech Magazine自体については、開発者向けの情報源というべきなのか、開発に興味のあるエンドユーザー向けなのか、ソリューションプロバイダー向けなのか……「開発者向け」というにはやや記事ジャンルに偏りがあるように見えます。

具体的にどのジャンルに偏っているかといえば、UNIX shellとかAppleScript(!)。毎号にAppleScriptの関連記事が載っているとは言いませんが、けっこうな確率で掲載されています。

実際、2012年1月号(フリー)と3月号(450円)にはAppleScriptObjCの記事が掲載されており、参考になりました。

2012/05/13 モニタの解像度を取得する(複数モニタ対応)

Mac本体に接続されたディスプレイ(モニタ)の解像度を取得するAppleScriptについて、これまでにいろいろなものを紹介してきました。

なぜ、1つのやり方ですまないかといえば……System Eventsなどで直接ディスプレイ解像度を取得するような命令セットが用意されてこなかったためで……さまざまなやり方を組み合わせて求めてきました(とくに、AppleScript Studioのプログラム内に入れたときに使えるかどうかが問題でした。けっこう、Finderに対する命令がきかない場合があったりで、冷や汗をかかされました)。

scrn1.png

このような環境で試してみましたが、iPad 3をAir Displayを使って外付けディスプレイとして接続した場合には、「環境設定」には表示されるものの、OSの各種コマンドでAir Display接続したiPadの情報は取得できません。

disp5.png

scrn3.png

scrn2.png

注:以下のサンプルAppleScriptは、Air Display経由のiPad 3を「外した」状態で(MacBook Pro本体+外付けLCDの2モニタ構成で)実行しています

■方法1 FinderのDesktop WindowのScroll Areaのsizeを取得

複数ディスプレイのトータルのサイズを取得。個別のディスプレイのサイズについては取得できません。

スクリプト名:displaySize1
–http://piyocast.com/as/archives/73
tell application “System Events” to set {rightLimit, bottomLimit} to size of scroll area 1 in process “Finder”
–> {3840, 1251}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

■方法2 FinderのDesktop WindowのScroll Areaのsizeを取得

1つのモニタの情報のみ取得。

スクリプト名:displaySize2
–http://piyocast.com/as/archives/1560
tell (do shell script “/usr/sbin/system_profiler SPDisplaysDataType | grep Resolution”) to set {newR, newB} to {word 2 as number, word 4 as number} – get screen size for monitor

–> {1920, 1200}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

■方法3 com.apple.windowserverの設定ファイルを読み込む方法

1つのモニタだけの情報を取得するようになっているので、そもそも複数のモニタには対応していません。

スクリプト名:displaySize3
–http://piyocast.com/as/archives/1561
return {word 3 of (do shell script “defaults read /Library/Preferences/com.apple.windowserver | grep -w Width”), word 3 of (do shell script “defaults read /Library/Preferences/com.apple.windowserver | grep -w Height”)}

–> {”1920″, “1200″}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

■方法4 Finderでdesktop Windowのサイズを取得

複数モニタのトータルのデスクトップサイズを取得できます。モニタの位置によっては、マイナスの数値なども返ってきます。

スクリプト名:displaySize4
–http://piyocast.com/as/archives/1562
tell application “Finder”
  get bounds of window of desktop
  
–> {0, -51, 3840, 1200}
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

とりあえず、いままでのやり方を見直して……とりあえず、system_profilerコマンドを経由して複数のモニタの解像度を取得するようにしてみました。

スクリプト名:モニタの解像度を取得する(複数モニタ対応)
–17インチMacBook Pro本体ディスプレイ
set aRes to retDisplayResolution() of me
–> {{1920, 1200}}

–17インチMacBook Pro本体ディスプレイ(Main) + 外付け24インチモニタ(1920 x 1080)(Sub)の場合
set aRes to retDisplayResolution() of me
–> {{1920, 1200}, {1920, 1080}}

–17インチMacBook Pro本体ディスプレイ(Sub) + 外付け24インチモニタ(1920 x 1080)(Main)の場合
set aRes to retDisplayResolution() of me
–> {{1920, 1200}, {1920, 1080}}

–モニタ解像度を取得。複数モニタ接続時にはリストで列挙
on retDisplayResolution()
  
  
set sRes to do shell script “/usr/sbin/system_profiler SPDisplaysDataType | grep Resolution”
  
  
set sList to paragraphs of sRes
  
set resList to {}
  
  
repeat with i in sList
    set j to contents of i
    
set x1 to word 2 of j as number
    
set y1 to word 4 of j as number
    
set the end of resList to {x1, y1}
  end repeat
  
  
return resList
  
end retDisplayResolution

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2012/05/06 ASObjC Runner〜ASOCの機能にAppleScript的な記法を

ASObjC Runnerは、ASOCのスクリプト(テキストベース)の実行機能をMac OS X 10.6.xと10.7.xに提供するフリーのアプリケーションです。作者はShane Stanley。ほかにも、Late Nighet SoftwareのMark Alldrittなども協力しているとのこと。

asobjc1.png

ASOCは基本的には、ランタイムアプリケーション上で動作するものですが、ASObjC Runnerではテキストファイル形式のASOCのプログラムをそのまま実行します。

tell application “ASObjC Runner”

のtellブロック内にscriptを記述します。サンプルはmacosxautomation.comに掲載されているので、雰囲気を伺い知ることができます。

asoctable.png

……以前までは、ASobjC Runnerはあまり個人的な興味を喚起されない存在だったのですが、途中のバージョンアップで面白い要素が追加されました。

Cocoaのオブジェクトに対して標準的なAppleScriptの用語でアクセスできるようにする機能です。

正確にいえば……ASObjC Runner側で想定している範囲の機能について、ASObjC RunnerがAppleScript用語辞書を用意しており、その用語を使って一般的なAppleScript的なアプローチでScriptingが行えるというわけです。

AS用語辞書が提供されており、通常のAppleScript的な用語が利用できるのは、

リスト操作(ソートや検索など)、文字列操作(検索、置換、日付文字列書式指定など。正規表現による検索/置換文字列指定の機能を含む)、ファイル操作(情報取得、コピー、削除、移動、ファイル作成、plist読み書き)などのほか、プログレスバー付きダイアログの表示

などです(ASOC的記法で書けば、より広い範囲のCocoaの機能をダイレクトに使用できます)。

2012/05/04 iPhotoで選択中の写真から曜日別の件数を個別にカウント

iPhotoで選択中の写真からファイル作成日付を取得し、それぞれの写真の撮影曜日を取得して日曜日〜土曜日の各曜日の撮影枚数を集計するAppleScriptです。

iPhoto上で写真を(複数、かつ大量に)選択状態にしておき、本AppleScriptを実行すると撮影曜日ごとの枚数を集計します。

やはりというか、当然というべきなのか、土曜日と日曜日の撮影が多いという結果に。

スクリプト名:iPhotoで選択中の写真から曜日別の件数を個別にカウント
script spdUp
  property selList : missing value
  
property dList : {}
end script

–set t1 to current date

–データの初期化
set dList of spdUp to {}
set selList of spdUp to {}

–iPhotoからデータを取得する
tell application "iPhoto"
  set selList of spdUp to selection
  
  
if (selList of spdUp) = {} then
    display dialog "何も選択されていません。" buttons {"OK"} default button 1
    
return
  end if
  
  
repeat with i in (selList of spdUp)
    set the end of (dList of spdUp) to (date of i)
  end repeat
end tell

set {n1, n2, n3, n4, n5, n6, n7} to {0, 0, 0, 0, 0, 0, 0}

repeat with i in (dList of spdUp)
  set j to contents of i
  
set aWDnum to weekday of j as number
  
if aWDnum = 1 then
    set n1 to n1 + 1
  else if aWDnum = 2 then
    set n2 to n2 + 1
  else if aWDnum = 3 then
    set n3 to n3 + 1
  else if aWDnum = 4 then
    set n4 to n4 + 1
  else if aWDnum = 5 then
    set n5 to n5 + 1
  else if aWDnum = 6 then
    set n6 to n6 + 1
  else if aWDnum = 7 then
    set n7 to n7 + 1
  end if
end repeat

return {n1, n2, n3, n4, n5, n6, n7}

–> {309, 10, 9, 10, 17, 51, 375}
–{Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2012/05/03 iPhotoで選択中の写真から各月の件数を個別にカウント

iPhotoで選択中の写真から、1か月単位で撮影枚数を個別にカウントするAppleScriptです。

iPhotoの「人々」を用いて任意の人物の写真をすべて選択しておき、

iphoto2.png

その状態で本AppleScriptを実行すると、各写真の日付情報を取得。日付情報をソートして開始月、終了月の情報を求め、各月にどの程度の写真撮影が行われたかを順次カウントして集計します。

iPhotoにいちいちアクセスするとスピードの低下が心配されるところですが、選択中の写真の日付情報を取得したらあとはiPhotoにアクセスせずに処理を行うため、781枚の写真を選択した状態で、93秒(MacBook Pro 2010 Core i7 2.66GHz、Mac OS X 10.6.8、8GB)で処理を終了しました。処理のほとんどは、iPhotoで選択中の写真の情報を取得する部分で、ソートや集計はほぼ一瞬です。

「○月には遊びに行ってなかったので1枚も撮っていなかったが、さすがに正月は撮影枚数が多いな」

などという、プログラムで分析するまでもない、予想どおりの傾向が分かります。

年ごとの集計、曜日ごとの集計などいろいろ集計のバリエーションを増やしてみると楽しいことでしょう。たぶん、「土日に撮影している枚数が多い」という結果が出るんでしょうけれども。期間で集計するほかに、撮影時の緯度・経度で集計するなど、さまざまな応用が考えられます。

スクリプト名:iPhotoで選択中の写真から各月の件数を個別にカウント
script spdUp
  property selList : missing value
  
property dList : {}
  
property eList : {}
  
property fList : {}
end script

–set t1 to current date

–データの初期化
set dList of spdUp to {}
set eList of spdUp to {}
set selList of spdUp to {}

–iPhotoからデータを取得する
tell application “iPhoto”
  set selList of spdUp to selection
  
  
if (selList of spdUp) = {} then
    display dialog “何も選択されていません。” buttons {“OK”} default button 1
    
return
  end if
  
  
repeat with i in (selList of spdUp)
    set the end of (dList of spdUp) to date of i
  end repeat
end tell

–ソート
set (dList of spdUp) to shellSort5(dList of spdUp) of me

–選択中の写真の最初の日付、最近の日付を求める
set minDate to contents of first item of (dList of spdUp)
set maxDate to contents of last item of (dList of spdUp)

–開始日、終了日の間の{年,月}のリストを取得する
set mmList to retYearMonthWithinPeriod(minDate, maxDate) of me

set aLen to length of (dList of spdUp)
set hitList to {}

set aCount to 0

set aPointer to 1
set hitF to false

repeat with i in mmList
  set {aYear, aMonth} to i
  
set sDate to (aYear as string) & “/” & (aMonth as string) & “/1″
  
set eDate to (aYear as string) & “/” & (aMonth as string) & “/” & getMlen(aYear, aMonth) of me as string
  
set sDateObj to date sDate
  
set eDateObj to date eDate
  
  
  
repeat
    set j to contents of item aPointer of (dList of spdUp)
    
if (sDateObj j) and (j eDateObj) then
      
      
if hitF = false then
        set hitF to true
        
set aCount to 1
        
        
set aPointer to aPointer + 1
        
      else
        set aCount to aCount + 1
        
set aPointer to aPointer + 1
      end if
      
    else
      
      
if hitF = true then
        set the end of hitList to {aYear, aMonth, aCount}
        
set aCount to 0
        
set hitF to false
        
exit repeat
      else
        set the end of hitList to {aYear, aMonth, 0}
        
exit repeat
      end if
      
    end if
    
    
if aPointer > aLen then
      exit repeat
    end if
    
  end repeat
  
  
if aPointer > aLen then
    exit repeat
  end if
  
end repeat

if hitF = true then
  set the end of hitList to {aYear, aMonth, aCount}
end if

–set t2 to current date
–set t3 to t2 -t1
–> 93 sec

hitList
–> {{2009, 4, 2}, {2009, 5, 0}, {2009, 6, 0}, {2009, 7, 25}, {2009, 8, 0}, {2009, 9, 0}, {2009, 10, 1}, {2009, 11, 2}, {2009, 12, 7}, {2010, 1, 38}, {2010, 2, 41}, {2010, 3, 4}, {2010, 4, 36}, {2010, 5, 5}, {2010, 6, 3}, {2010, 7, 36}, {2010, 8, 26}, {2010, 9, 49}, {2010, 10, 8}, {2010, 11, 61}, {2010, 12, 23}, {2011, 1, 32}, {2011, 2, 40}, {2011, 3, 0}, {2011, 4, 26}, {2011, 5, 44}, {2011, 6, 10}, {2011, 7, 32}, {2011, 8, 41}, {2011, 9, 0}, {2011, 10, 0}, {2011, 11, 39}, {2011, 12, 51}, {2012, 1, 25}, {2012, 2, 0}, {2012, 3, 51}, {2012, 4, 23}}

on retYearMonthWithinPeriod(sDate, eDate)
  
  
set sYear to year of sDate
  
set sMonth to month of sDate as number
  
  
set eYear to year of eDate
  
set eMonth to month of eDate as number
  
  
set mList to {}
  
  
if sYear is equal to eYear then
    
    
repeat with i from sMonth to eMonth
      set the end of mList to {sYear, i}
    end repeat
    
  else if sYear + 1 = eYear then
    
    
repeat with i from sMonth to 12
      set the end of mList to {sYear, i}
    end repeat
    
    
repeat with i from 1 to sMonth
      set the end of mList to {eYear, i}
    end repeat
    
  else
    
    
repeat with i from sMonth to 12
      set the end of mList to {sYear, i}
    end repeat
    
    
repeat with i from (sYear + 1) to (eYear - 1)
      repeat with ii from 1 to 12
        set the end of mList to {i, ii}
      end repeat
    end repeat
    
    
repeat with i from 1 to sMonth
      set the end of mList to {eYear, i}
    end repeat
    
  end if
  
  
return mList
end retYearMonthWithinPeriod

–最大値を取得する
on maximumFromList(nList)
  script o
    property nl : nList
  end script
  
  
set max to item 1 of o’s nl
  
repeat with i from 2 to (count nList)
    set n to item i of o’s nl
    
if n > max then set max to n
  end repeat
  
return max
  
end maximumFromList

–最小値を取得する
on minimumFromList(nList)
  script o
    property nl : nList
  end script
  
  
set min to item 1 of o’s nl
  
repeat with i from 2 to (count nList)
    set n to item i of o’s nl
    
if n < min then set min to n
  end repeat
  
return min
  
end minimumFromList

–指定月の長さを得る(日数)
on getMlen(aYear, aMonth)
  
  
set aDat to (aYear as text) & “/” & (aMonth as text) & “/1″
  
if aMonth is not equal to 12 then
    set eDat to ((aYear as text) & “/” & (aMonth + 1) as text) & “/1″
  else
    set eDat to ((aYear + 1) as text) & “/” & (1 as text) & “/1″
  end if
  
  
–set sDat to date aDat
  
set eDat to date eDat
  
set eDat to eDat - 1
  
  
set mLen to day of eDat
  
return mLen
  
end getMlen

–プレーンなAppleScriptベースでは最速ソート
on shellSort5(aSortList) – スクリプトオブジェクトを使用
  script oBj
    property list : aSortList
  end script
  
set len to count oBj’s list’s items
  
set gap to 1
  
repeat while (gap len)
    set gap to ((gap * 3) + 1)
  end repeat
  
repeat while (gap > 0)
    set gap to (gap div 3)
    
if (gap < len) then
      repeat with i from gap to (len - 1)
        set temp to oBj’s list’s item (i + 1)
        
set j to i
        
repeat while ((j gap) and (oBj’s list’s item (j - gap + 1) > temp))
          set oBj’s list’s item (j + 1) to oBj’s list’s item (j - gap + 1)
          
set j to j - gap
        end repeat
        
set oBj’s list’s item (j + 1) to temp
      end repeat
    end if
  end repeat
  
return oBj’s list
end shellSort5

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に