MoreBeerMorePower

Power Platform中心だけど、ノーコード/ローコード系を書いてます。

Power Automate で配列をシャッフルする方法

はじめに

Twitterで見かけたブログで、Power Automateの配列をランダムにする方法が出ていました。この方法では、Azure FunctionsをHTTPアクションで呼び出して配列のランダム化を実行しています。

montemagno.com

でもFunctionsを使うまでもないような気がしたので、方法を検討してみました。

結果としては比較的簡単な方法で順序をシャッフルした配列が生成できました。使ったアクションは「選択」「作成」のみです。

f:id:mofumofu_dance:20201006151815p:plain
配列をシャッフルするフローの全体

サンプルをGithubに置いてあります。インポートして試してみてください。

PowerApps365/ShuffleArray_sample.zip at master · mofumofu-dance/PowerApps365 · GitHub

準備

ここでは簡単のために、上の記事と同じ配列を入力にしておきます。なるべくセットアップは同一にしておくという目的で、 「変数の初期化」アクションでこの配列を作成しました。タイプは「アレイ」です。

[
  { "Id": "@{guid()}", "Name": "Abdullah Hamed" },
  { "Id": "@{guid()}", "Name": "James Montemagno" },
  { "Id": "@{guid()}", "Name": "Jayme Singleton" },
  { "Id": "@{guid()}", "Name": "Jeff Fritz" },
  { "Id": "@{guid()}", "Name": "Jon Galloway" },
  { "Id": "@{guid()}", "Name": "Nish Anil" }
]

f:id:mofumofu_dance:20201006151849p:plain
配列変数の初期化。GUIDは各行をユニークにするために付与している。

ステップ1 : ランダムな整数の配列を生成する

まずはランダムな整数 (元の配列の行数) × 100個を含む配列を作ります。 ランダムな整数ならなんでもいいというわけではなく、あとあと配列のインデックスに使いたいので、 0~(元の配列の行数)−1 の範囲でランダムな整数を生成します。

つまり上の配列であれば行数は6なので、

[4,5,2,1,4,2,3,1,1,0.....]

のように0~5までの整数で作られる600行の配列です。

これを作るために「選択」アクションを利用します。選択アクションの入力はそれぞれ以下のように設定してください。

From

@{range(0,mul(length(variables('Arr')),100))}

Map

@int(string(rand(0,length(variables('Arr')))))

f:id:mofumofu_dance:20201006152525p:plain
特定の値の範囲でランダムな整数配列を生成する

これで期待する配列が生成されました。

ステップ2 : 値の重複を排除する

ステップ1で作った配列は、当然ですが同じ数が何度も出てきます。この重複を排除するために union関数を利用します。

union関数では配列を2つ与えることで、2つの配列を統合し、重複を除いた結果を返してくれます。

ステップ1の「選択」アクションに続けて、「作成」アクションを追加し、以下を入力に入れてください。

@{union(body('Generate_random_array'),range(0,length(variables('Arr'))))}

『ステップ1で生成した配列』と、『0~(元の配列の行数)−1』を順に並べた配列 (この例では [0,1,2,3,4,5] )をunionしています。これにより 重複が排除された0~(元の配列の行数)−1 の整数を含む整数配列 が生成されます。

f:id:mofumofu_dance:20201006153612p:plain
ランダムな順序の生成結果

ステップ3: ランダムな順番に並べる

最後に、ステップ2で得られた順番に元の配列をマッピングしてあげます。「選択」アクションを追加して、以下のように設定します。

From

@{outputs('Generate_random_order')}

Map

@variables('Arr')?[item()]

どういうことをやっているのかは、下図の右下にあるイメージを見てみてください。

f:id:mofumofu_dance:20201006154429p:plain
ステップ3の選択アクションの動作イメージ

おわりと補足

以上で配列から順番をシャッフルした配列をループもなく、Azure Functionsを使うこともなく、生成できました。

念のため、本当にランダムっぽいのかを確認してみました。

ここで紹介した操作を1000回ループさせてみて、生成された配列の先頭が、元の配列の何番目だったのかをカウントした結果です。

f:id:mofumofu_dance:20201006155330p:plain
生成された配列のランダム具合をチェックした結果

統計がそれほどないのでがたついていますが、まあまあ許容できる範囲かなという印象です。

こんな風に、比較的簡単な操作で配列をシャッフルすることができますので、ぜひ試してみてください。