Archive for 5月, 2013

2013/05/26 AppleScriptエディタのURLプロトコルに複数バージョン

http://www.macosxautomation.comを読んでいたら、掲載AppleScriptでファイル名を指定しているものがあることに気付き、同様にファイル名を指定してHTML書き出しを行うAppleScriptを書きました。

実際にファイル名を指定したURLプロトコルリンクで掲載しているサンプルも幾つかあります。

メニューバーにログインユーザー状態を表示

リンクしているURLの内容は、こんな感じです。

applescript://com.apple.scripteditor?action=new&name=メニューバーにログインユーザー状態を表示&script=…..(省略)

ところが……古いバージョンのOSでは、「name=」でファイル名を指定したURLプロトコルだとAppleScriptエディタ側がURLを受け取れません。具体的には、Mac OS X 10.4や10.6あたりだと完全にダメです(身の回りに10.7の環境がなくて調べ切れていません)。

結局、ファイル名を指定しないURLで掲載するように戻したのですが、どのバージョンのMac OS Xから名前付きのURLを扱えるようになったのか、調べておく必要を感じます。

追記:Mac OS X 10.7の環境(初代MacBook Air)が修理から帰ってきたので試してみました。……name属性を指定すると、10.7でもAppleScriptエディタに転送できないことが分りました。これは、ちょっとまずいかも、、、

2013/05/24 Finder上で選択中のファイルをPreviewでオープンして保存してクローズ

Finder上で選択中のファイル(たぶんPDF)をPreview.appでオープンして、保存してクローズ……を繰り返すAppleScriptです。

PhotoshopでPDFを加工したところ、そのままではファイルサイズが大きく、古いOS(Mac OS X 10.4.11とか)では内容を確認できない状態でした。

……ちょっと困りました。そこで、OS X 10.8上のPreview.appでファイルを保存し直したところ、ファイルサイズも小さくなり、古いOSでもオープンできるようになりました。

何か、ほかにも回避方法はありそうですが……とりあえず、本AppleScriptによって、Finder上でPhotoshopによる加工を行ったPDFを選択しておき、Scriptを実行することですべて保存し直します。

なお、本AppleScriptはGUI Scriptingを利用しているため、あらかじめシステム環境設定の「アクセシビリティ」で「補助装置にアクセスできるようにする」にチェックを入れておく必要があります。また、将来のOSバージョンアップによってPreview.appのメニュー内容が変更になった場合には、そのままでは動かず修正(メニューアイテム番号部分のみ)が必要になる可能性が高いです。

スクリプト名:Finder上で選択中のファイルをPreviewでオープンして保存してクローズ
tell application “Finder”
  set aList to selection as alias list
end tell

repeat with i in aList
  
  
set j to contents of i
  
set jj to j as string
  
  
–Preview.appで選択されたファイルをオープンする
  
set appBundleID to “com.apple.Preview”
  
tell application “Finder”
    open file jj using application file id appBundleID
  end tell
  
  
delay 0.1
  
  
–Preview.appでファイル保存→クローズを行う
  
activate application “Preview”
  
tell application “System Events”
    tell process “プレビュー”
      click menu item 8 of menu 1 of menu bar item 3 of menu bar 1 –保存
    end tell
  end tell
  
  
delay 0.1
  
  
tell application “System Events”
    tell process “プレビュー”
      click menu item 5 of menu 1 of menu bar item 3 of menu bar 1 –閉じる
    end tell
  end tell
  
end repeat

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

2013/05/19 iTunes 11.0.2〜11.0.3 AppleScript系変更点まとめ

iTunes史上最大のAppleScript系機能の変更・拡充が行われた、iTunes 11.0.3およびその1つ前のバージョンである11.0.2の変更点をまとめてみました。

■iTunes 11.0.2
device playlistが廃止された

■iTunes 11.0.3
propertiesで各種オブジェクトの属性情報をまとめて取得できるようになった。

AirPlayの制御のためのオブジェクトと属性情報が用意された。
AirPlay enabled:アプリケーションの属性。AirPlayが使用可能だとtrue
current AirPlay devices:AirPlayで使用中のデバイスを示すアプリケーションの属性。
AirPlay device:AirPlayデバイス。nameやindexで識別可。各種属性値を持つ。

player position:現在再生中のTrackの再生位置(秒)。従来はintegerでしか取得/指定できなかったものが、小数点以下の情報まで扱えるようになった

special kind:playlistのspecial kindから、 「Party Shuffle」が削除された

device:sourceのkindから「device」が削除された

device playlist:sourceに含まれるplaylistの中から「deveice playlist」が削除された

device track:playlistに含まれるtrackから「device track」が削除された

iTunes U:trackに属性値「iTunes U」が追加された(read only)

home video:trackの属性値にvideo kindに「home video」が追加された

2013/05/17 iTunes 11.0.3で出力可能なすべてのAirPlay Deviceに同時出力する

iTunes 11.0.3以降で、現在出力可能なAirPlay Deviceすべてを出力先に指定し、音声の同時出力を行うAppleScriptです。

airplay2.png

MacBook Pro Retina本体と、無線LAN経由でつながっている居間のApple TVに同時に出力を行わせて……もちろん、無線LAN経由なので、出力デバイスごとに若干のディレイは発生しますが、ちょっと面白い感じ(エコー?)がしていいと思います。

スクリプト名:iTunes 11.0.3で出力可能なすべてのAirPlay Deviceに同時出力する
tell application “iTunes”
  set dList to every AirPlay device
  
set current AirPlay devices to dList
end tell

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

2013/05/17 iTunes 11.0.3でアプリケーションの状態を取得する

iTunes 11.0.3がリリースされ、AppleScript関連で大幅な改修が行われました。iTunesのAppleScript系の機能においては、過去最大の改修といってもよいかもしれません。

iTunes 11.0.2まではずーーーーーーっとできなかった、各種属性を「properties」でまとめて取得する記法を受け付けるようになりました。

スクリプト名:iTunes 11.0.3でアプリケーションの状態を取得する
tell application “iTunes”
  properties
end tell

–> {class:application, name:”iTunes”, player state:stopped, version:”11.0.3″, frontmost:false, sound volume:100, mute:false, visuals enabled:false, full screen:false, visual size:large, EQ enabled:false, fixed indexing:false, player position:missing value, converting:false, current stream title:missing value, current stream URL:missing value, AirPlay enabled:false, current AirPlay devices:{AirPlay device id 26 of application “iTunes”}}

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

もちろん、Trackのpropertiesなども取れます。いままでの、かったるいiTunes Scriptingとは雲泥の差です。

さらに、AirPlayの状態取得や設定が行えるようになりました。

スクリプト名:iTunes 11.0.3でAirPlay Deviceすべての詳細情報を取得する
tell application “iTunes”
  set dList to every AirPlay device
  
–> {AirPlay device id 26, AirPlay device id 88476}
  
  
repeat with i in dList
    set j to contents of i
    
    
properties of j
    
    
–> {class:AirPlay device, id:26, index:1, name:”コンピュータ”, persistent ID:”0000000000000000″, active:false, available:true, kind:computer, network address:missing value, protected:false, selected:true, supports audio:true, supports video:true, sound volume:100}
    
    
–> {class:AirPlay device, id:88476, index:2, name:”Apple TV”, persistent ID:”00005855CA413D01″, active:false, available:true, kind:Apple TV, network address:”58:55:ca:41:3d:01″, protected:false, selected:false, supports audio:true, supports video:true, sound volume:100}
    
  end repeat
  
end tell

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

airplay1.png

スクリプト名:iTunes 11.0.3で指定可能なAirPlay Deviceから選択して、AirPlay出力先を指定する
tell application “iTunes”
  
  
set dList to every AirPlay device
  
set nList to name of every AirPlay device
  
  
set aSel to choose from list nList
  
set aaSel to first item of aSel
  
  
set current AirPlay devices to AirPlay device aaSel
  
end tell

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

AirPlayの状態も取得できます。ただし、この「AirPlay Enabled」というアプリケーションの属性値がRead Onlyなので、AirPlayの状態を解除する方法の模索が必要です。

スクリプト名:iTunes 11.0.3でAirPlayの状態を取得する
tell application “iTunes”
  set airPF to AirPlay enabled
  
–> false
end tell

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

一応、AirPlay Deviceを「コンピュータ」にすればAirPlay Offと似た状態になるようなので、そこから先に何かをすべきなのかもしれません。

AirPlayの出力先デバイスの変更は、再生中にも行うことができました。

スクリプト名:iTunes 11.0.3で現在利用可能なAirPlayデバイス一覧を取得する
tell application “iTunes”
  set curAirPlay to current AirPlay devices
  
–> {AirPlay device id 26 of application “iTunes”}
  
end tell

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

2013/05/17 選択した書類ファイルをDockのアプリアイコンにドラッグ&ドロップ

選択した書類ファイルを、任意の(Bundle IDで指定した)アプリのDock上のアイコンにドラッグ&ドロップ……するのと同じ状態を作るAppleScriptです。

まず最初にお断りしておきますが、(AppleScriptObjCではない)通常のAppleScriptにドラッグ&ドロップの状態を作り出す機能はありません。

ありませんが、「任意のアプリで指定ファイルをオープンさせる」という機能がFinderにあります。GUIのフィードバックやDockへのドラッグ&ドロップ通知がないだけで、実行される内容はほぼ同じです。

まずは、どのアプリでオープンさせるかを調べるために、Finder上でアプリケーションのアイコンファイルを選択しておき、こんな(使い捨てレベルの)AppleScriptを実行。

スクリプト名:Finder上でアプリケーションを選択しておいて実行すると詳細情報をログ表示
tell application “Finder”
  set {a} to selection
  
properties of a
end tell

–> {class:application file, name:”Art Text 2.app”, index:38, displayed name:”Art Text 2″, name extension:”app”, extension hidden:true, container:folder “Applications” of startup disk of application “Finder”, disk:startup disk of application “Finder”, position:{92, 775}, desktop position:missing value, bounds:{60, 743, 124, 807}, kind:”アプリケーション”, label index:0, locked:false, description:missing value, comment:”", size:122256097, physical size:128839680, creation date:date “2013年4月12日金曜日 12:22:40″, modification date:date “2013年4月14日日曜日 12:47:54″, icon:missing value, URL:”file://localhost/Applications/Art%20Text%202.app”, owner:”システム”, group:”root”, owner privileges:read write, group privileges:read write, everyones privileges:read only, file type:”APPL”, creator type:”ARTT”, stationery:false, product version:”", version:”Art Text, version 2.4.1, Copyright © 2006-2012 BeLight Software, Ltd”, id:”com.belightsoft.ArtText2″, accepts high level events:true, has scripting terminology:false}

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

すると、選択したアプリケーションの詳細情報が表示されますので……「id」情報を調べます。ここでは、AppleScriptに非対応の「Art Text 2」の情報を表示しています。

Art Text 2のBundle IDが、「com.belightsoft.ArtText2」だと分ったので、これを次のAppleScriptに反映させ、選択したファイル(ファイル情報だけ渡せば別にダイアログ表示する必要はない)をオープンさせるようにします。

スクリプト名:指定ファイルを指定アプリでオープン(アプリアイコンへの書類ファイルのドラッグ&ドロップと等価)
set a to choose file

set appBundleID to “com.belightsoft.ArtText2″ –オープンさせたいアプリケーションのBundle ID

tell application “Finder”
  open file a using application file id appBundleID
end tell

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

だいたいは、AppleScript非対応のアプリケーションで、書類をドラッグ&ドロップすると自動でファイル変換を行ってくれるようなものをAppleScriptからコントロールするために利用することが多いです(ファイルの変換を行うものとか、エンコーダーとか)。

もちろん、指定したアプリが対応していない種類のファイルを開かせようとしても、開けません。どのような種類のファイルに対応しているかは、あらかじめ調べておく必要があります。

ここで指している「アプリケーション」とは、CocoaベースのMac OS Xの標準的なアプリケーションのことを指しています。Javaで作られたものや、クロスプラットフォーム開発ツールで作られた特殊なアプリケーションなどは対象外です。

2013/05/16 メニューバーにメッセージ(旧称iChat)の状態を表示

メニューバーにメッセージ(旧称iChat)の状態を表示するAppleScriptです。

ichat.png

スクリプト名:メニューバーにメッセージ(旧称iChat)の状態を表示
do shell script "open /System/Library/CoreServices/Menu\\ Extras/iChat.menu"

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

2013/05/16 メニューバーに音量の状態を表示

メニューバーに音量の状態を表示するAppleScriptです。

sound.png

スクリプト名:メニューバーに音量の状態を表示
do shell script "open /System/Library/CoreServices/Menu\\ Extras/Volume.menu"

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

2013/05/16 メニューバーにログインユーザー状態を表示

メニューバーにログインユーザー状態を表示するAppleScriptです。

login.png

スクリプト名:メニューバーにログインユーザー状態を表示
do shell script “open /System/Library/CoreServices/Menu\\ Extras/User.menu”

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

2013/05/16 メニューバーにTime Machineの状態を表示

メニューバーにTime Machineのインジケーターを表示するAppleScriptです。

tm.png

スクリプト名:メニューバーにTime Machineの状態を表示
do shell script "open /System/Library/CoreServices/Menu\\ Extras/TimeMachine.menu"

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

2013/05/16 メニューバーに文字入力メニューを表示

メニューバーに文字入力メニュー(日本語入力時に文字入力モードやインプットメソッドの種別表示を行う)を表示するAppleScriptです。

textinput.png

スクリプト名:メニューバーに文字入力メニューを表示
do shell script “open /System/Library/CoreServices/Menu\\ Extras/TextInput.menu”

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

2013/05/16 メニューバーにScript Menuを表示

メニューバーにScript Menuを表示するAppleScriptです。

scriptmenu.png

スクリプト名:メニューバーにScript Menuを表示
do shell script “open ‘/System/Library/CoreServices/Menu Extras/Script Menu.menu’”

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

2013/05/16 メニューバーに手書き入力(Ink)オプションを表示

メニューバーに手書き入力(Ink)オプションを表示するAppleScriptです。

InkはMac OS X 10.2以降で標準搭載された、英語の文字入力認識入力(手書き入力タブレットなどを併用して入力)です。

ink.png

スクリプト名:メニューバーに手書き入力(Ink)オプションを表示
do shell script "open /System/Library/CoreServices/Menu\\ Extras/Ink.menu"

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

2013/05/16 メニューバーにモバイルホームオプションを表示

メニューバーにモバイルホームオプションを表示するAppleScriptです。

mobhome.png

スクリプト名:メニューバーにモバイルホームオプションを表示
do shell script "open /System/Library/CoreServices/Menu\\ Extras/HomeSync.menu"

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

2013/05/16 メニューバーにFaxオプションを表示

メニューバーにFaxオプションを表示するAppleScriptです。

fax.png

スクリプト名:メニューバーにFaxオプションを表示
do shell script "open /System/Library/CoreServices/Menu\\ Extras/Fax.menu"

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

2013/05/16 メニューバーにイジェクトボタンを表示

メニューバーにイジェクトボタンを表示するAppleScriptです。

Menu Extraをオープンしているだけですが、割と役立ちます。

ただし、MacBook Airなど光学ドライブ非搭載のマシンで実行しても、とくにイジェクトすべきドライブが見当たりません。

menu3.png

スクリプト名:メニューバーにイジェクトボタンを表示
do shell script "open /System/Library/CoreServices/Menu\\ Extras/Eject.menu"

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

2013/05/16 メニューバーにディスプレイミラーリングオプションを表示

メニューバーにディスプレイミラーリングオプションを表示するAppleScriptです。

menu2.png

スクリプト名:メニューバーにディスプレイミラーリングオプションを表示
do shell script "open /System/Library/CoreServices/Menu\\ Extras/Displays.menu"

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

2013/05/16 メニューバーに時計を表示する

メニューバーに時計を表示するMenu ExtraをオープンするAppleScriptです。

clock.png

スクリプト名:メニューバーに時計を表示する
do shell script “open /System/Library/CoreServices/Menu\\ Extras/Clock.menu”

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

2013/05/16 メニューバーにBluetoothの状態を表示する

メニューバーにBluetoothの状態を表示するインジケーターを表示するAppleScriptです。

bt.png

スクリプト名:メニューバーにBluetoothの状態を表示する
do shell script “open /System/Library/CoreServices/Menu\\ Extras/Bluetooth.menu”

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

2013/05/16 メニューバーにバッテリーの状態を表示する

メニューバーにバッテリーの状態を表示するインジケーターを表示するAppleScriptです。

batt.png

スクリプト名:メニューバーにバッテリーの状態を表示する
do shell script “open /System/Library/CoreServices/Menu\\ Extras/Battery.menu”

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

2013/05/16 メニューバーにWiFiの状態を表示する

メニューバーにWiFilの状態を表示する(Menu Extraをオープンする)AppleScriptです。

wifi.png

メニューバーにWiFiの状態表示インジケータが表示されていなかった場合に、本Scriptを実行すると表示状態になります。

スクリプト名:メニューバーにバッテリーの状態を表示する
do shell script “open /System/Library/CoreServices/Menu\\ Extras/Battery.menu”

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

2013/05/16 メニューバーにUniversal Accessの状態を表示する

メニューバーにUniversal Accessの状態を表示するAppleScriptです。

やっている内容自体はしょーもないもの(Menu Extraをただオープンするだけ)ですが、資料化しておくとあとで便利そうだったので掲載することにしました。

menu1.png

スクリプト名:メニューバーにUniversal Accessの状態を表示する
do shell script “open /System/Library/CoreServices/Menu\\ Extras/UniversalAccess.menu”

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

2013/05/16 開始文字と終了文字を指定してトリミング。開始文字出現後にそのまま終了文字を開始文字の次から検索

指定文字列に対して、別々の文字を指定して前後からトリミングを行います。

たいていはそれぞれ前後から(開始文字は前から、終了文字は後ろから)検索してトリミング処理しますが、本ルーチンでは、とりあえず先頭から開始文字列を検索し、見つかった位置の次の文字から終了文字列を後ろに向かって検索。見つかったらトリミングを行います。

用途は……テストデータを見るとまるわかりですが、Mail.appで指定のMessageの親フォルダ(Mail.app上のフォルダ構造において)を求めるときに、AppleScriptObjCのプロジェクト内でうまく処理が行えなかったので、従来使っていたものを書き換える際に作成したものです。

スクリプト名:開始文字と終了文字を指定してトリミング。開始文字出現後にそのまま終了文字を開始文字の次から検索
set aMes to «class mbxp» \”仕事系/ABC/ABC_ML/_my_work_related/ひよこインキ/HIYOKOINK\” of application \”Mail\” のタイプを string に変換できません。”

set aRes to trimStrFromToSequential(aMes, “\”", “\”") of me
–> “仕事系/ABC/ABC_ML/_my_work_related/ひよこインキ/HIYOKO”

–開始文字と終了文字を指定してトリミング。開始文字出現後にそのまま終了文字を開始文字の次から検索
on trimStrFromToSequential(aStr, fromStr, toStr)
  –fromStrは前から探す
  
if fromStr is not equal to “” then
    set sPos to (offset of fromStr in aStr) + 1
  else
    set sPos to 1
  end if
  
  
–toStrはfromStrの次から前から探す
  
if toStr is not equal to “” then
    set b to text (sPos + 1) thru -1 of aStr
    
set ePos to (offset of toStr in b)
    
set ePos to ((length of aStr) - ePos - 1)
  else
    set ePos to length of aStr
  end if
  
set aRes to text sPos thru ePos of aStr
  
return aRes
end trimStrFromToSequential

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

2013/05/11 USTREAMの番組をテスト配信

本Blogの使い方をかんたんに説明する番組をためしに作ってみました。


ust1.png

↑画像クリックで配信ページへ

2013/05/11 AppleScriptObjCプログラム内で外部プログラムを制御するコードを分離する

これは、AppleScriptObjCの実用性のレベルを上げるための、きわめて重要なノウハウです。

ASOCプログラム内で外部プログラムをコントロールする困難

AppleScriptObjC(ASOC)のプログラムに、Mail.appやiTunes、InDesignやPhotoshopなどの外部プログラムをコントロールするコードをまぜて、AppleScript Studioと同様にワークフローの自動化を行うプログラムを作ろうとして…………ちょっと大きなプログラムを組むと、壁に当たってしまいます。

1つのハンドラ内で終止するような小規模なプログラムであれば問題はありません。

外部アプリケーションのオブジェクトをハンドラ間ではやりとりできない

問題は、アプリケーションのオブジェクトを変数に入れて、サブルーチンを呼び出したとたんにエラーが発生すること。ハンドラをまたいで外部アプリケーションのオブジェクトをやりとりすることが、AppleScriptObjCのランタイムではうまくできません。

たとえば、clicked_イベントハンドラ内で、Mail.app上で選択中のメッセージを取得し、そのオブジェクトへの参照を変数に代入。サブルーチンを呼び出して、詳細情報を取り出して調べ、抽出したオブジェクトを戻そうとするとエラーになってしまいます。

外部アプリケーションをコントロールするAppleScriptは、ASOCとは別ファイルに、通常のAppleScriptで

このため、外部アプリケーションを制御するコードについては、通常のAppleScriptで(AppleScriptエディタで)書いておいて、XcodeでASOCのプロジェクトに入れます。

xc1.png

ASOCのプロジェクト内で、追加したAppleScriptは/Contents/Resourcesフォルダに入れられることになります。

ASOCのプログラム側でアプリケーションバンドル内の/Contents/Resourcesフォルダ内に置かれている、通常形式のAppleScriptをload scriptで変数なりプロパティなりに読み込んで、パラメータを与えつつ実行します。

xc2.png

通常形式のAppleScriptからの戻り値には外部アプリケーションのオブジェクトを入れないようにして、IDの数値であるとか、リスト、テキストなどで値を返します。

Xcode上では通常形式のAppleScript(scptファイル)を編集することやコンパイル(バイトコードへのコンパイル)を行うことは(途中のバージョンからは)できなくなりましたが、書き換えが必要な場合にはAppleScriptエディタを用いて書き換えを行うことになります。

AppleScript Studioでも外部アプリ操作用Scriptを分離していた

結局、AppleScript Studioの時代にも、外部アプリケーションをコントロールするAppleScriptコードはメインのAppleScript Studioのコードからは分離して、load scriptで読み込んで実行を行っていました。AppleScriptObjCで大規模なプログラムを、外部プログラムをコントロールするコードを含んだかたちで開発するのであれば、AppleScriptObjCのコードと通常のAppleScriptのコードを分離する必要があるというのが正しい認識のようです。

AppleScriptエディタ上でもCocoa-AppleScript(AppleScriptObjCとほぼ同じもの)を書けるようになっています。ただし、AppleScriptエディタ上でCocoa-AppleScriptのプログラムを書いた場合でも、Cocoa-AppleScript(=AppleScriptObjC)のコードを起動時に実行し、メインのScriptをload scriptして実行するようになっています。

AppleScriptObjCのランタイムと、通常のAppleScriptのランタイムでは動作が異なっており、外部アプリケーションをコントロールする機能を持たせる場合には、分離して作成することが必須と考えて間違いないでしょう。

2013/05/10 数値の2D Listから最大値を求める v4

入れ子のリスト(2次元配列)から最大値を求めるAppleScriptです。

これまで利用していた「入れ子リストのフラット化(FlattenList)」のサブルーチンが、高速なのはいいものの、リスト中の要素がすべて文字列になってしまうので、再帰で処理するルーチンをみつけてきて使ってみました。

また、不要な(マヌケな)処理がややあったので、そこのあたりはバッサリ切っています。高速化のための努力はしていないので、要素数が数千(4000以上?)に上るような処理の場合には高速化対策を考えたほうがよいでしょう。

2DのList(2次元配列)と書いていましたが、動作原理上とくに2Dである必要はなく、3Dでも4Dでも大丈夫です。

スクリプト名:数値の2D Listから最大値を求める v4
–入れ子の数値リストの最大値を求める
set rlist to {{0, 0, 0, 0, 0, 0}, {0, 1, 1, 0, 0, 0}, {1, 0, 0, 0, 1, 0}, {1, 0, 0, 1, 1, 0}, {1, 1, 1, 1, 5, 0}, {0, 0, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0}}

set aRes to getMaxFrom2DList(rlist) of me
–> 5

–2D Listから最大値を求める
on getMaxFrom2DList(rlist)
  set r2List to FlattenList(rlist) of me –2Dリストを1Dに変換
  
set maxItem to contents of first item of shellSortDescending(r2List)
  
return maxItem
end getMaxFrom2DList

–再帰タイプのリストのフラット化
–http://rosettacode.org/wiki/Flatten_a_list#AppleScript
on FlattenList(aList)
  if class of aList is not list then
    return {aList}
  else if length of aList is 0 then
    return aList
  else
    return FlattenList(first item of aList) & (FlattenList(rest of aList))
  end if
end FlattenList

–入れ子ではないリストの降順ソート
on shellSortDescending(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 shellSortDescending

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

2013/05/02 数値の2D Listから最大値を求める

数値から構成される入れ子の2Dのリスト(2次元配列)から最大値を求めるAppleScriptです。

ほとんどありものを使っただけで、ほとんど書いていませんが……AppleScriptObjCのプロジェクトに入れるために作成しました。

少量のデータを処理することを想定しているため、大量のデータ処理のための高速化は施していません。

スクリプト名:数値の2D Listから最大値を求める
–入れ子の数値リストの最大値を求める
set rlist to {{0, 0, 0, 0, 0, 0}, {0, 1, 1, 0, 0, 0}, {1, 0, 0, 0, 1, 0}, {1, 0, 0, 1, 1, 0}, {1, 1, 1, 1, 5, 0}, {0, 0, 1, 1, 0, 0}, {0, 0, 0, 0, 0, 0}}

set aRes to getMaxFrom2DList(rlist) of me
–> 5

–数値の2D Listから最大値を求める
on getMaxFrom2DList(rlist)
  set r2List to FlattenList(rlist) –2Dリストを1Dに変換
  
set r3List to {}
  
repeat with i in r2List
    set the end of r3List to i as number
  end repeat
  
set maxItem to contents of first item of shellSortDescending(r3List)
  
  
return maxItem
end getMaxFrom2DList

–By Paul Berkowitz
on FlattenList(aList)
  set oldDelims to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to {“????”}
  
set aString to aList as text
  
set aList to text items of aString
  
set AppleScript’s text item delimiters to oldDelims
  
return aList
end FlattenList

–入れ子ではないリストの降順ソート
on shellSortDescending(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 shellSortDescending

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