今日のお題は『一定の規則で並んだテキストをプログラムで処理して並び替える』というものです。こうした処理は、定型処理によくあるものです。基本的な方法を学ぶことで、いろいろなデータに応用できます。さっそく、詳しいお題を確認してみましょう。
FBで実際にあった依頼
なお、今回のお題は、Facebookで見つけたものです。日本のオープンソース界を大いに盛り上げているびぎねっとの宮原さんが「一杯奢る」のでプログラムを作って欲しいと書き込んでいたものです。それは、以下のようなものでした。
以下のような4行でひとまとまりのデータを表すテキストファイルがあります。これを日付順(新しい順)に並び替えるプログラムを作ってください。
日付1
タイトル1
URL1
日付2
タイトル2
URL2
日付3
タイトル3
URL3
...
これを図にしてみると、以下のようになります。
筆者は「これならすぐ作れるし、いつもお世話になっているから作ろう!」と思ったのです。しかし、いつもみんなのために頑張っている宮原さんのため、あるいは「一杯奢る」の威力が凄かったため(?)、あっという間に、たくさんの方がこの問題を解いてしまっていました。
とは言え、この手のネタは定期的にあるものです。そこで、読者の皆さんと一緒に、プログラムを作って、次回奢ってもらえる機会に備えることにしましょう!
ポイントはデータを一つずつ分けて配列に入れること
そもそも、手元のテキストデータを任意の順番で並び替えたいという場面は意外と多いものです。それでは、この問題をなでしこで解いていきましょう。
こうしたテキストのデータを処理する場合、だいたい一つのデータが一行になっているものが多いものです。その代表的なデータが、CSV形式のデータです。しかし、今回のお題のデータでは、四行ごと(三行のデータ+空行)で、一つのデータとなっています。この特徴を掴んで、データを二次元配列に変換して処理するとうまく処理できます。一度、配列変数に変換する理由ですが、なでしこの内部形式である配列形式にしてしまえば、並び替え(ソート)などのデータ処理が容易になるからです。
手順を図にしてみると、以下のようになります。テキストデータを二次元配列変数に変換し、そこで並び替えなどの処理を行います。そして、処理後にテキスト形式で出力するという手順です。
ただし、筆者の経験上、この手のデータは手動で作成するため、データがたくさんあると正しく四行ずつになっていることは希です。どういう事かと言うと、途中に間違って入力した不完全なデータ(日付とURLだけでタイトルが抜けている、または、無駄な改行が多く含まれている)が紛れ込んでいることが多くあるからです。そのため、データの間違いをチェックする機構も一緒に作ることが多いです。ですが、今回はプログラムをシンプルにするために、多少壊れたデータでも対処できる仕組みを考えてみます。
このデータの並びですが、よくよく見ると、各データの区切りに改行が二つあるという点に注目できます。そこで、改行二つを区切り記号にして区切れば、手軽にデータを分割できます。
以下のプログラムを、なでしこ3Web簡易エディタに貼り付けて実行してみましょう。
サンプル=『2019/07/14
日本語プログラミング言語「なでしこ」
https://nadesi.com
2019/7/1
Ruby
https://www.ruby-lang.org/ja/
2019/07/09
教育用プログラミング言語「ドリトル」
https://dolittle.eplang.jp/
』
# --- テキストデータを二次元配列に変換 --- (*1)
区切り文字=改行&改行
結果=[]
サンプルを区切り文字で区切って反復
対象をトリムして、改行で区切る。
それを結果に配列追加。
ここまで。
# --- 日付順に並び替える --- (*2)
「日付順関数」で結果を配列カスタムソート。
●日付順関数(A,B)
TA = A[0]をUNIXTIME変換
TB = B[0]をUNIXTIME変換
それはTB - TA
ここまで。
# --- 結果を表示する --- (*3)
結果を反復
対象[0]を表示
対象[1]を表示
対象[2]を表示
「」を表示。
ここまで。
プログラムを簡易エディタに貼り付けて「実行」ボタンを押して実行すると、以下のように表示されます。日付に注目してみると、正しく新しい順に並んでいるのを確認できます。
プログラムを確認してみましょう。プログラムの前半はサンプルデータです。そして、後半が実際のプログラムです。(*1)の部分では、テキストデータを二次元配列に変換します。方法としては、ひとまとまりのデータを改行二つで区切ります。そして、各データを改行で分割するというものです。
そして、(*2)の部分では日付順に並び替えます。大抵のプログラミング言語には、配列を任意の順番で並び替える命令が用意されています。なでしこにも、命令『配列カスタムソート』があります。これを使って、日付順に並び替えます。
最後に(*3)の部分で、二次元配列変数をテキスト形式に変換して出力します。
使いやすくUIを作ろう
さて、ここまでのプログラムで、おおまかなプログラムは完成しました。今度は、プログラムを手軽に実行できるように、操作画面であるUIを作成してプログラムを完成させましょう。
# --- UIの作成 --- (*1)
DOM親要素に『
<div id="frm">入力:<br>
<textarea id="input"></textarea><br>
<button id="conv_btn">変換</button><br>
<textarea id="output"></textarea></div>
』をHTML設定。
『#frm textarea』に、{"width":"99%", "height":"150px", "background-color":"#FFF0F0"}を、DOMスタイル一括設定。
「#conv_btn」をクリックした時には
変換処理実行。
ここまで。
# --- 変換処理 --- (*2)
●変換処理実行とは
「#input」のテキスト取得して、入力データに代入。
区切り文字=改行&改行
結果=[]
入力データを区切り文字で区切って反復
対象をトリムして、改行で区切る
それを結果に配列追加。
ここまで。
「日付順関数」で結果を配列カスタムソート。
# --- 出力データを作成する --- (*3)
F出力=「」
結果を反復
F日付=対象[0]
Fタイトル=対象[1]
FURL=対象[2]
F出力=F出力&「{F日付}{改行}{Fタイトル}{改行}{FURL}{改行}{改行}」
ここまで。
「#output」にF出力をテキスト設定。
ここまで。
●日付順関数(A,B)
TA = A[0]をUNIXTIME変換
TB = B[0]をUNIXTIME変換
それはTB - TA
ここまで。
上記のプログラムを、同じように、なでしこ3Webエディタに貼り付けて実行してみましょう。そして、入力テキストを「入力:」のすぐ下のテキストボックスに貼り付けて「変換」ボタンを押します。すると、変換ボタンの下に実行結果が表示されます。
プログラムを確認してみましょう。(*1)の部分で操作画面のUIを作成します。ここでは、HTMLをべた書きしてUIを作成しています。なでしこから操作するために、操作したい要素に『id="名前"』のような属性をつけておきます。そうすると、なでしこのプログラムから「#名前」のような名前でDOMオブジェクトを操作できます。
そして、(*2)の部分では、「#input」と名付けたテキストボックスからテキストを取得して、処理を行い、「#output」と名付けたテキストボックスにデータを設定するというものです。整形処理については、一つ目のプログラムとほとんど同じです。異なる点は、(*3)の部分で出力データを文字列で生成するようにしています。もし、データの並び順を変えたい場合には、変数「F出力」の部分の並び方を調整します。
まとめ
以上、今回は、なでしこでテキストデータを並び替えるプログラムを紹介しました。テキスト処理を行う場合は、元のテキストデータを上手に解析して、配列変数に変換するのがポイントでした。
また、ここで作ったプログラムは、ある程度、データが壊れていても、適当にデータを処理できるようにしていますが、より正確なデータが必要な場合には、日付の形式が正しいかどうか簡単なチェックを入れるなど、データの確認機構も入れると親切でしょう。
なお、Facebookのこの投稿には、さまざまな方法で問題を解く方法が書き込まれていて、それを眺めるだけでも面白いものになっていました。また、SNSで面白い投稿を見つけたら、なでしこで解く方法を解説したいと思います。
自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2005年IPAスーパークリエイター認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。