見出し画像

Notionで無理やり乱数(っぽい数値)を生成して記事の並び順をランダムにする方法

おひさしぶりです、ねここです。
最近、あまり触れていなかったNotionを触るスイッチが久々にONになってしまったので、仕事そっちのけでアレコレいじり倒してます(仕事しよ?)

乱数が欲しい

そんな中で、
「乱数使って定期的に記事の並べ替えをしたい!!!」
という場面が何度か発生してしまったのですが、ご存じの通りNotionに乱数生成の機能は実装されていないので、無理やりそれっぽい数字を生成できないものかと試行錯誤していました。
たぶん先人も全員通ってきた道だとは思いますし、すでにノウハウ、ナレッジはありそうな気はしますが、こういうのを自力で考えるのも頭の体操というものです。(探し回ったけどいいナレッジが見つからなかった、というわけじゃないんだからね!) 

ということで、それっぽい乱数を生成する方法を考えた成果を書き残しておきたいと思います。

乱数が欲しい場面

乱数生成して記事を並び替えを活用できそうな用途としては、

  • 過去に書いたものを定期的に浮上させて振り返りの機会をなんとなく作る

  • 単語帳を作って、ランダムに並べ替えをする

  • 愛猫の写真をいっぱい収納したDBをギャラリー表示にしてほっこりする

みたいなところでしょうか。写真の内容は各自テキトウに読み替えてください。
特に単語帳とかはニーズがありそうな気がしますね。そこをターゲットにした並べ替え機能、実装したりしないですか、公式さん???

乱数っぽいものを生成するための要素

さて、乱数生成機能がないところで乱数っぽいものを生成するにはどうすればよいでしょう。
まず、現在時刻を取得してあれこれすることはできそうです。
現在時刻は now( ) で取得することができます。
また、取得した日時は , , , , に分解することもできます。

システム互換の都合で秒、ミリ秒まで表現する領域は保有してるみたいですが、
情報としては分までしか保持してません。

この現在時刻(とくに分のところ)をうまく使うことで、1分単位で変動する乱数っぽいものを作っていくことになります。
また活用として、
1分じゃなく1時間おきに並び替え:分は使わず時のパラメータを使う
30分おきに:分を30で割って端数を切り捨てた値を使う
など、工夫すれば自分にあったチューニングができます。

次は、記事ごとに異なる情報を持ちうる要素を考えます。

  • 作成日時

  • 最終更新日時

  • 記事タイトル(の長さ)

  • 記事ID

作成日時と最終更新日時は現在日時と同じ方法で年月日時分を取り出すことができます。
記事タイトルは length 関数を使用することで、文字列の長さを取得できます。
無題だったら 0 ですし、この記事のタイトルをそのまま使ったら 41 になります。

半角全角に関わらず1文字単位で取得してるようですね。

そして記事ID。
Notionはページを作成すると、自動で32バイトのIDが設定されます。
記事IDは id 関数で取得できます。

スラッシュから後ろの部分が記事ID

このIDは16進数なので、うまく10進数に戻すことができればいい感じに使えそうですが、悲しいことに16進数をいい感じに10進数に変換する手段が提供されていません。
数式を駆使してできないこともないと思いますが、明らかにコストと成果が見合いませんw

ということで、無いなら無いなりにうまく活用しなければいけません。
どうするかというと、この記事IDにtoNumber関数を無理やり当て込みます。

toNumber関数で記事IDの先頭部分から取得できる限りの数字を取得
(本来あるべき使い方では絶対にない)
こんな感じで記事ごとの数字が取れます。

toNumber関数の挙動として、与えられた引数を先頭から見ていって、数値として許容できる部分までを拾い、アルファベットを検出した時点で後ろをすべて捨てているようです。A~Fで始まるものは0になります。
確率的には4割弱が0になるわけですが、そこは我慢することにしましょう。
基数変換できたらなぁ

ということで、現在時刻、記事作成日時、記事最終更新日時、記事タイトルの長さ、記事IDの可食部toNumberで取り出せる数字を獲得できました。

乱数っぽいものを生成する

あとはこれを足したり引いたり掛けたり割ったりラジバンダリ、いい感じの乱雑な数値を生成します。
といっても、これが決定版! みたいな方法があるわけでもなく、各々のセンスで組み立てていくことになります。冴えたやりかたをご存じの方、きれいにばらける方法を作れた方はコメント欄に情報ください。

とはいえ、あとは頑張ってね! というのもあれなので、ぼくがこれうまくいったと思っているアイデアをひとつ。
それは
絶対に割り切れない割り算をして、小数部を一部分だけ拾ってくる
というものです。

絶対に(おそらく、たぶん)割り切れない割り算をする方法

では、割り切れない割り算をどうするのか。
Notionにはいい感じに小数を返す関数が存在します。
自然対数を取る関数 ln と、自然対数eの数値乗を返す関数 exp です。
(この記事2度目の本来あるべきではない使い方) 

(作成日時の分+現在時刻の分)の平方根をlnにぶち込んでみたり

こんな感じで求めた数値を分母にして割り算をするとだいたい割り切れず、小数部分も(使いたい範囲では)循環しない値が求まります。

結果の小数部が同じようなものばかりになったら、
もう少し数式を工夫することになります

小数部を一部分だけ拾ってくる方法

ここまでできたら、あとは小数部分をもぎ取るのみです。
方法としては、10のn乗点を右に動かし、mod演算(余りを求める計算)をします。
たとえば、上表の一番上の結果「91.420583410637」から小数点以下第2位から第5位、「2058」を取り出すには、
(割り算の結果) * 100000 をして小数点を6桁右に動かし、10000で割った余りを取得します。

% は余りを求める演算子
floor は端数を切り捨てる関数

すると、以下のような結果が返ってきます。

こんな感じになります

これだけでわりとそれっぽい乱数になりますし、数式を工夫することで値を拾ってくる箇所や桁数を自由にいじることができます。
91.420583410637:(割り算の結果) * 1000 % 1000 (端数切捨て) = 420
91.420583410637:(割り算の結果) * 10000 % 100000 (端数切捨て) = 14205
91.420583410637:(割り算の結果) * 100000000 % 100 (端数切捨て) = 41

あとは並び替えるだけ!

こうやってもぎ取った数値を並べ替えのキーにすれば、一定時間ごとに並び変わります(自動では切り替わらないので、ビューを切り替えるとかなんらかの更新を掛けるとかする必要はあります)。
あとは実際にどんな感じで並び変わるかを見ながら、いい感じに入れ替わるように数式を調整していくのみです。

あとがき

ということで、Notionで乱数っぽいものを生成する方法でした。
(乱数を生成、とは間違っても言えない)

途中、toNumberやlnなど本来の使い方ではない関数の活用をしていたりもしますが、求めている結果がちゃんと返ってくるのであれば、それで全然OKだとぼくは思っています。特に自分だけが使うのであれば。
むしろこういうときじゃないとexpとかlnとか絶対使わないじゃん。

わりと勢いで書いた記事ではありますが、今回紹介した方法で「うまくランダム並べかえできた!」とか「こういう式とかパラメータ使うほうがきれいだぜ」とか「そもそも、もっといい方法知ってるぜ」とかあれば、ぜひコメントとかで教えていただけると嬉しいです。


ここまで書いて、今の時期だったらどこかのアドベントカレンダーに割り込んでこの記事を書けばよかったのかもしれん、とか思ったけど、いいやw

24.2.19 追記

今回の内容が実際にNotion上で動くページを作りました。
よければどうぞ。


この記事が気に入ったらサポートをしてみませんか?