LoginSignup
1
0

JSONataのシャッフル

Last updated at Posted at 2023-12-03

Node-REDでランダムにデータを作りたいと思ってフローを書いていたら、簡単そうなことなのに、ちょっとつまずきました。
ことの顛末と解決方法について書きたいと思います。

こんな事象

やりたかったこと

aからeまでの5つの文字からランダムに文字を取得したい。

そこで、こんな感じのJSONata式を書きました。

["a", "b", "c", "d", "e"][$floor($random()*5)]

処理の意味としては、
$random()を使用して、0以上1未満のランダムな小数を生成して、配列の長さをかけ算します。
$floor()を使用して小数点以下を切り捨て、ランダムな整数のインデックスを得ます。
得られたインデックスを使用して、対象の配列からランダムな文字を取得します。

これでできそうと思ってフローを作り、実行してみました。

やってみたら、うまくいかない

いざ、injectノードをクリックしてみると、うまく一文字だけ出力されたり、時折、["a","d"]といった風に2個でてきたり、Undefined になったりします。

image.png

環境は、enebularで動いているNode-RED v3.0.2-n.1です。

解決方法

FunctionノードとJSONata式の2通りの方法を試したところ、うまくいきました。
いずれもChatGPT 3.5に聞きました😅

Functionノードでの解決

FunctionノードでJavaScriptを書いて解決する方法です。いずれもChatGPTに聞いたところ、

// ランダムな文字を選択する配列
const characters = ["a", "b", "c", "d", "e"];

// ランダムなインデックスを生成
const randomIndex = Math.floor(Math.random() * characters.length);

// ランダムな文字を取得
const randomCharacter = characters[randomIndex];

// 結果を出力
msg.payload = randomCharacter;
return msg;

image.png

ちゃんとランダムな文字列が出てきました。
ですが、うまくいって当然な気もします。

JSONataでの解決

次に、改めてJSONata式でやってみます。
今度は、$randomではなく、$shuffleを使います。

$shuffle(["a", "b", "c","d", "e"])[0]

処理の意味としては、
$shuffle()を使用して、配列の値の順番をごちゃまぜにします。
得られた配列の一番最初の値(0番目)を取得すれば結果的にランダムになります。

image.png

まとめ

Node-REDでフローを分かりやすく書きたいときにJSONataを重宝しています。
シャッフルなんて知らなかったですが、もっと早く気がつけばよかったです。
教えてくれたChatGPTに感謝します。JSONata式は奥が深いです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0