皆さんのディクショナ​リの活用方法、聞かせ​てください

Kojiro Saito on 19 Jun 2025 at 6:41 (Edited on 20 Jun 2025 at 4:43)
Latest activity Edit by Kojiro Saito on 20 Jun 2025 at 4:43

キーと値の組み合わせでデータを格納できるディクショナリ。R2022bdictionaryコマンドが登場し、最近のバージョンではreaddictionarywritedictionaryJSONファイルからの読み込み・書き込みにも対応しました。
私はMIDIデータからピアノの演奏動画を作るプログラムで、ディクショナリを使いました。音のノート番号をキーにして、patchで白と黒で鍵盤を塗りつぶしたmatlab.graphics.Graphicsデータ型を値にしたディクショナリで保存して、MIDIで鳴らされた音のノート番号からlookupでグラフのオブジェクトを取得し、FaceColorを変更してハイライトするというもの。
コード例
%% MIDIデータの.matファイルを読み取ってピアノを描画するサンプル
fig = figure('Position', [34 328 1626 524]);
ax = axes;
whiteKeyY = [0 0 150 150];
whiteKeyColor = [1 1 1];
blackKeyY = [50 50 150 150];
blackKeyColor = [0.1 0.1 0.1];
edgeColor = [0 0 0];
% ディクショナリの定義
d = configureDictionary("double", "matlab.graphics.Graphics");
% 白鍵を描画
for n = 1:9
pos = 23*7*(n-1);
d = insert(d, 21 + (n-1)*12, patch([pos+5 pos+28 pos+28 pos+5],whiteKeyY, whiteKeyColor, 'EdgeColor', edgeColor, 'UserData', 21 + (n-1)*12));
d = insert(d, 23 + (n-1)*12, patch([pos+28 pos+51 pos+51 pos+28], whiteKeyY, whiteKeyColor, 'EdgeColor', edgeColor, 'UserData', 23 + (n-1)*12));
d = insert(d, 24 + (n-1)*12, patch([pos+51 pos+74 pos+74 pos+51], whiteKeyY, whiteKeyColor, 'EdgeColor', edgeColor, 'UserData', 24 + (n-1)*12));
if n < 9
d = insert(d, 26 + (n-1)*12, patch([pos+74 pos+97 pos+97 pos+74], whiteKeyY, whiteKeyColor, 'EdgeColor', edgeColor, 'UserData', 26 + (n-1)*12));
d = insert(d, 28 + (n-1)*12, patch([pos+97 pos+120 pos+120 pos+97], whiteKeyY, whiteKeyColor, 'EdgeColor', edgeColor, 'UserData', 28 + (n-1)*12));
d = insert(d, 29 + (n-1)*12, patch([pos+120 pos+143 pos+143 pos+120], whiteKeyY, whiteKeyColor, 'EdgeColor', edgeColor, 'UserData', 29 + (n-1)*12));
d = insert(d, 31 + (n-1)*12, patch([pos+143 pos+166 pos+166 pos+143], whiteKeyY, whiteKeyColor, 'EdgeColor', edgeColor, 'UserData', 31 + (n-1)*12));
end
end
% 黒鍵を描画。白鍵の上になるようにループを分けています
for n = 1:9
pos = 23*7*(n-1);
d = insert(d, 22 + (n-1)*12, patch([pos+23 pos+33 pos+33 pos+23], blackKeyY, blackKeyColor, 'EdgeColor', [0 0 0], 'UserData', 22 + (n-1)*12));
if n < 9
d = insert(d, 25 + (n-1)*12, patch([pos+69 pos+79 pos+79 pos+69], blackKeyY, blackKeyColor, 'EdgeColor', [0 0 0], 'UserData', 25 + (n-1)*12));
d = insert(d, 27 + (n-1)*12, patch([pos+92 pos+102 pos+102 pos+92], blackKeyY, blackKeyColor, 'EdgeColor', [0 0 0], 'UserData', 27 + (n-1)*12));
d = insert(d, 30 + (n-1)*12, patch([pos+138 pos+148 pos+148 pos+138], blackKeyY, blackKeyColor, 'EdgeColor', [0 0 0], 'UserData', 30 + (n-1)*12));
d = insert(d, 32 + (n-1)*12, patch([pos+161 pos+171 pos+171 pos+161], blackKeyY, blackKeyColor, 'EdgeColor', [0 0 0], 'UserData', 32 + (n-1)*12));
end
end
xticklabels({})
yticklabels({})
xlim([5 1362])
drawnow
%% MIDI音源の.matファイルを読み込み
matData = load('fur-elise.mat');
msg = matData.receivedMessages;
eventTimes = [msg.Timestamp] - msg(1).Timestamp;
n = 1;
numNotes = 0;
lastNote = 0;
highlightedCircles = cell(1, 127);
% 音が鳴った鍵盤だけハイライトする
tic
while toc < max(eventTimes)
if toc > eventTimes(n)
thisMsg = msg(n);
if thisMsg.Type == "NoteOn"
numNotes = numNotes + 1;
lastNote = thisMsg.Note;
thisPatch = lookup(d, thisMsg.Note);
thisPatch.FaceColor = '#CCFFCC';
drawnow
elseif thisMsg.Type == "NoteOff"
numNotes = 0;
thisPatch = lookup(d, thisMsg.Note);
[~, ~, wOrB] = calcNotePos(thisMsg.Note);
if wOrB == "w"
thisPatch.FaceColor = 'white';
else
thisPatch.FaceColor = 'black';
end
drawnow
end
n = n+1;
end
end
%% サブ関数
function [pianoPos, centerPos, wOrB] = calcNotePos(note)
tempVar = idivide(int64(note), int64(12)); % 12で割った商
pos = 23*7*(tempVar-1);
switch mod(note, 12)
case 0 % C
pianoPos = pos + 62.5;
centerPos = 30;
wOrB = "w";
case 2 % D
pianoPos = pos + 85.5;
centerPos = 30;
wOrB = "w";
case 4 % E
pianoPos = pos + 108.5;
centerPos = 30;
wOrB = "w";
case 5 % F
pianoPos = pos + 131.5;
centerPos = 30;
wOrB = "w";
case 7 % G
pianoPos = pos + 154.5;
centerPos = 30;
wOrB = "w";
case 9 % A
pianoPos = pos + 177.5;
centerPos = 30;
wOrB = "w";
case 11 % B
pianoPos = pos + 200.5;
centerPos = 30;
wOrB = "w";
case 1 % C#
pianoPos = pos + 69;
centerPos = 100;
wOrB = "b";
case 3 % D#
pianoPos = pos + 92;
centerPos = 100;
wOrB = "b";
case 6 % F#
pianoPos = pos + 138;
centerPos = 100;
wOrB = "b";
case 8 % G#
pianoPos = pos + 161;
centerPos = 100;
wOrB = "b";
case 10 % A#
pianoPos = pos + 184;
centerPos = 100;
wOrB = "b";
end
end
皆さんはディクショナリを使ってますか? もし使っていたら、どういう活用をしているか、聞かせてください!
Jiro Doke
Jiro Doke on 19 Jun 2025 at 13:29
dictionary は使い方を勉強する時にサンプルを作ったくらいなので,ちょうど良いシナリオが思い浮かびませんでしたが,この例を見てディクショナリの使い道が分かった気がします.patch を作りながら動的にディクショナリが作れるのはいいですよね.多分自分だったら無理やり table 型で音→patchの対応表を作ってたと思います.
ところで,このプログラムのコード欲しい!子供のピアノ練習用に動画作りたい...
Kojiro Saito
Kojiro Saito on 19 Jun 2025 at 13:45
構造がなくてキーで引っ張ってくれば十分なデータだとディクショナリ使っちゃいますね。lookupで値をパッと引っ張ってくるのが楽しいです。
ピアノ打鍵のプログラム、少し小綺麗にしてから元の投稿に付けておきますね!
Kojiro Saito
Kojiro Saito on 20 Jun 2025 at 3:02
@Jiro Dokeさん、コードを追加しました! 音は鳴らず描画のみの例です。
Hernia Baby
Hernia Baby on 19 Jun 2025 at 12:56

正直、使い方?というかメリットがイマイチわからなかったですが、JSONファイルがMATLABで扱えるんですね。 これは可能性を感じる(ง ˘ω˘ )ว

Kojiro Saito
Kojiro Saito on 19 Jun 2025 at 13:41
構造体とテーブルとセルがあればだいたい何とかなりますもんね。ディクショナリならではの良さはlookupの検索の速さかなと個人的に思っています。
ちなみにR2023bからreadstructwritestructがJSONファイルに対応したので、JSONから構造体として正確に読み取れるようになってます。これもオススメ。
Hernia Baby
Hernia Baby on 19 Jun 2025 at 14:15

( ‘ᾥ’ )…←readstructたちのせいでdictionaryの良さがまたピンとこなくなった顔

michio
michio on 19 Jun 2025 at 8:59
> matlab.graphics.Graphicsデータ型を値にしたディクショナリで保存
がテクいですね。
Kojiro Saito
Kojiro Saito on 19 Jun 2025 at 11:13
色々なデータ型が入れられるディクショナリの寛容さですねw