つくばねの峰より落つるみなの川恋ぞ積りて淵となりぬる
Advent Calendar 2022 62日目1の記事です。
I'm looking forward to 12/25,2022
私のAdvent Calendar 2022 一覧。
はじめに
Elixirを楽しんでいますか
今日は.md
内のテーブルをソートしてみます。
Enum.sort_by/3を使います。
仕様
仕様は以下の通りとします。
-
README.md
の構造はかわらないものとする- 特にテーブルの列は変わらないものとする
- テーブルの行は増えることがある
- テーブルの並び順は基本的に以下の順番とする
- Category順(UTF-8の文字列順)
- Name順(UTF-8の文字列順)
- Languageは
Japanese
を優先、他はUTF-8の文字列順 - URL順(UTF-8の文字列順)
- ただし、Category=Etcはテーブルの後方に置く
並び替えの仕様が複雑です。
サンプル
サンプルを示します。
Input
InputのREADME.mdはこういうものです。
# Awesome Twitter Communities for Engineers
[![Build Status](https://github.com/mattn/awesome-twitter-communities/actions/workflows/lint.yaml/badge.svg?branch=main)](https://github.com/mattn/awesome-twitter-communities/actions/workflows/lint.yaml?query=branch%3Amain)
|Name|Category|Language|URL|
|-|-|-|-|
|AWS|Cloud Infrastructure|English|<https://twitter.com/i/communities/1471503983839567878>|
|WebRTC|Communication technology|English|<https://twitter.com/i/communities/1498133315164860419>|
|Kubernetes|Container|English|<https://twitter.com/i/communities/1444745802383953921>|
|Kubernetes & コンテナ技術|Container|Japanese|<https://twitter.com/i/communities/1498974495989956614>|
|MySQL-JP|Database|Japanese|<https://twitter.com/i/communities/1496795585982382084>|
|NewSQL_jp|Database|Japanese|<https://twitter.com/i/communities/1498603867285581824>|
|自作DBMS友の会|Database|Japanese|<https://twitter.com/i/communities/1498114917672505344>|
|OSS 日本語 L10n|Localization|Japanese|<https://twitter.com/i/communities/1498961283546157061>|
|Linuxカーネル|OS|Japanese|<https://twitter.com/i/communities/1499543572189618176>|
|vyosjp|OS|Japanese|<https://twitter.com/i/communities/1498101007733370880>|
|.NET_Japan|Programming Language|Japanese|<https://twitter.com/i/communities/1496977662640009217>|
|C++|Programming Language|Japanese|<https://twitter.com/i/communities/1499396722514345984>|
|Deno-ja|Programming Language|Japanese|<https://twitter.com/i/communities/1498174921562013698>|
|F# on Twitter|Programming Language|English|<https://twitter.com/i/communities/1493280005589196801>|
|Java|Programming Language|Japanese|<https://twitter.com/i/communities/1497219281079398402>|
|Java|Programming Language|English|<https://twitter.com/i/communities/1471178821906821122>|
|Julia Programming Language|Programming Language|English|<https://twitter.com/i/communities/1441046367514755082>|
|Julia言語|Programming Language|Japanese|<https://twitter.com/i/communities/1499390501467811845>|
|PHP-ja|Programming Language|Japanese|<https://twitter.com/i/communities/1497741277789835264>|
|Pythonジャパン|Programming Language|Japanese|<https://twitter.com/i/communities/1498184748728205315>|
|The Go Programming Language|Programming Language|English|<https://twitter.com/i/communities/1493637136502960134>|
|TypeScript|Programming Language|Japanese|<https://twitter.com/i/communities/1499329858178289664>|
|WebAssembly|Programming Language|English|<https://twitter.com/i/communities/1497545442023944192>|
|clojure|Programming Language|English|<https://twitter.com/i/communities/1494013093059432451>|
|dotnet|Programming Language|English|<https://twitter.com/i/communities/1488624124817666051>|
|elixir|Programming Language|English|<https://twitter.com/i/communities/1493287155942232066>|
|elixir-jp|Programming Language|Japanese|<https://twitter.com/i/communities/1498232167864082435>|
|ruby-jp|Programming Language|Japanese|<https://twitter.com/i/communities/1496768365683408900>|
|サバイバルTypeScript|Programming Language|Japanese|<https://twitter.com/i/communities/1499723154956390401>|
|プログラミング言語Go|Programming Language|Japanese|<https://twitter.com/i/communities/1498095077222400000>|
|プログラミング言語Rust|Programming Language|Japanese|<https://twitter.com/i/communities/1498496039401451522>|
|プログラミング言語処理系|Programming Language|Japanese|<https://twitter.com/i/communities/1499381283864342530>|
|Security Engineering|Security|Japanese|<https://twitter.com/i/communities/1498138021723467781>|
|Webセキュリティ|Security|Japanese|<https://twitter.com/i/communities/1498053973097730048>|
|VS Codeの会|Text Editor|Japanese|<https://twitter.com/i/communities/1498865559353511941>|
|emacs-jp|Text Editor|Japanese|<https://twitter.com/i/communities/1498276712034947072>|
|vim-jp|Text Editor|Japanese|<https://twitter.com/i/communities/1497961032404594691>|
|Ebiten|Tools/Libraries|Japanese|<https://twitter.com/i/communities/1498350105346600960>|
|Flutter|Tools/Libraries|English|<https://twitter.com/i/communities/1472249315724771329>|
|Jotai Friends JP|Tools/Libraries|Japanese|<https://twitter.com/i/communities/1497150937806213120>|
|Nuxt|Tools/Libraries|English|<https://twitter.com/i/communities/1498235047194808320>|
|SATySFi|Tools/Libraries|Japanese|<https://twitter.com/i/communities/1498074334619123712>|
|Spring Developers|Tools/Libraries|English|<https://twitter.com/i/communities/1496544801533091844>|
|Svelte日本|Tools/Libraries|Japanese|<https://twitter.com/i/communities/1499182207491260424>|
|DATA Saber|Etc|Japanese|<https://twitter.com/i/communities/1498660583415361536>|
|IE11を偲ぶ会|Etc|Japanese|<https://twitter.com/i/communities/1498870842784043009>|
|ITエンジニアを褒める会|Etc|Japanese|<https://twitter.com/i/communities/1494319842585083906>|
|JMUG|Etc|Japanese|<https://twitter.com/i/communities/1498585537527320577>|
|Japan Okta User Group|Etc|Japanese|<https://twitter.com/i/communities/1498432461839036418>|
|SREとかObservabilityとか|Etc|Japanese|<https://twitter.com/i/communities/1498088713670172675>|
|Tech Twitter|Etc|English|<https://twitter.com/i/communities/1472105760389668865>|
|Tech Twitter - Japan|Etc|Japanese|<https://twitter.com/i/communities/1494649689215737856>|
|Twitter Developers Japan|Etc|Japanese|<https://twitter.com/i/communities/1493041080077795328>|
|UdonCreatorCommunity|Etc|Japanese|<https://twitter.com/i/communities/1497068375553765378>|
|nlp-jp|Etc|Japanese|<https://twitter.com/i/communities/1498287599928365062>|
|sudo-jp|Etc|Japanese|<https://twitter.com/i/communities/1499227044982374401>|
|ウェブパフォーマンス|Etc|Japanese|<https://twitter.com/i/communities/1498089387422515202>|
|ガジェット|Etc|Japanese|<https://twitter.com/i/communities/1498224086652121099>|
|バンクーバー日本人ソフトウェアエンジニア|Etc|Japanese|<https://twitter.com/i/communities/1498574247895056384>|
|吉祥寺.pm|Etc|Japanese|<https://twitter.com/i/communities/1498106494989967363>|
|日本のウェブフォームを良くする開発者の会|Etc|Japanese|<https://twitter.com/i/communities/1498168121336614916>|
|自作キーボード|Etc|Japanese|<https://twitter.com/i/communities/1495468692813287425>|
|鹿児島ITエンジニア|Etc|Japanese|<https://twitter.com/i/communities/1496763936682954752>|
|ネットワーク自動化|Etc|Japanese|<https://twitter.com/i/communities/1498540422154821633>|
Output
これを正解とします。
# Awesome Twitter Communities for Engineers
[![Build Status](https://github.com/mattn/awesome-twitter-communities/actions/workflows/lint.yaml/badge.svg?branch=main)](https://github.com/mattn/awesome-twitter-communities/actions/workflows/lint.yaml?query=branch%3Amain)
|Name|Category|Language|URL|
|-|-|-|-|
|AWS|Cloud Infrastructure|English|<https://twitter.com/i/communities/1471503983839567878>|
|WebRTC|Communication technology|English|<https://twitter.com/i/communities/1498133315164860419>|
|Kubernetes|Container|English|<https://twitter.com/i/communities/1444745802383953921>|
|Kubernetes & コンテナ技術|Container|Japanese|<https://twitter.com/i/communities/1498974495989956614>|
|MySQL-JP|Database|Japanese|<https://twitter.com/i/communities/1496795585982382084>|
|NewSQL_jp|Database|Japanese|<https://twitter.com/i/communities/1498603867285581824>|
|自作DBMS友の会|Database|Japanese|<https://twitter.com/i/communities/1498114917672505344>|
|OSS 日本語 L10n|Localization|Japanese|<https://twitter.com/i/communities/1498961283546157061>|
|Linuxカーネル|OS|Japanese|<https://twitter.com/i/communities/1499543572189618176>|
|vyosjp|OS|Japanese|<https://twitter.com/i/communities/1498101007733370880>|
|.NET_Japan|Programming Language|Japanese|<https://twitter.com/i/communities/1496977662640009217>|
|C++|Programming Language|Japanese|<https://twitter.com/i/communities/1499396722514345984>|
|Deno-ja|Programming Language|Japanese|<https://twitter.com/i/communities/1498174921562013698>|
|F# on Twitter|Programming Language|English|<https://twitter.com/i/communities/1493280005589196801>|
|Java|Programming Language|Japanese|<https://twitter.com/i/communities/1497219281079398402>|
|Java|Programming Language|English|<https://twitter.com/i/communities/1471178821906821122>|
|Julia Programming Language|Programming Language|English|<https://twitter.com/i/communities/1441046367514755082>|
|Julia言語|Programming Language|Japanese|<https://twitter.com/i/communities/1499390501467811845>|
|PHP-ja|Programming Language|Japanese|<https://twitter.com/i/communities/1497741277789835264>|
|Pythonジャパン|Programming Language|Japanese|<https://twitter.com/i/communities/1498184748728205315>|
|The Go Programming Language|Programming Language|English|<https://twitter.com/i/communities/1493637136502960134>|
|TypeScript|Programming Language|Japanese|<https://twitter.com/i/communities/1499329858178289664>|
|WebAssembly|Programming Language|English|<https://twitter.com/i/communities/1497545442023944192>|
|clojure|Programming Language|English|<https://twitter.com/i/communities/1494013093059432451>|
|dotnet|Programming Language|English|<https://twitter.com/i/communities/1488624124817666051>|
|elixir|Programming Language|English|<https://twitter.com/i/communities/1493287155942232066>|
|elixir-jp|Programming Language|Japanese|<https://twitter.com/i/communities/1498232167864082435>|
|ruby-jp|Programming Language|Japanese|<https://twitter.com/i/communities/1496768365683408900>|
|サバイバルTypeScript|Programming Language|Japanese|<https://twitter.com/i/communities/1499723154956390401>|
|プログラミング言語Go|Programming Language|Japanese|<https://twitter.com/i/communities/1498095077222400000>|
|プログラミング言語Rust|Programming Language|Japanese|<https://twitter.com/i/communities/1498496039401451522>|
|プログラミング言語処理系|Programming Language|Japanese|<https://twitter.com/i/communities/1499381283864342530>|
|Security Engineering|Security|Japanese|<https://twitter.com/i/communities/1498138021723467781>|
|Webセキュリティ|Security|Japanese|<https://twitter.com/i/communities/1498053973097730048>|
|VS Codeの会|Text Editor|Japanese|<https://twitter.com/i/communities/1498865559353511941>|
|emacs-jp|Text Editor|Japanese|<https://twitter.com/i/communities/1498276712034947072>|
|vim-jp|Text Editor|Japanese|<https://twitter.com/i/communities/1497961032404594691>|
|Ebiten|Tools/Libraries|Japanese|<https://twitter.com/i/communities/1498350105346600960>|
|Flutter|Tools/Libraries|English|<https://twitter.com/i/communities/1472249315724771329>|
|Jotai Friends JP|Tools/Libraries|Japanese|<https://twitter.com/i/communities/1497150937806213120>|
|Nuxt|Tools/Libraries|English|<https://twitter.com/i/communities/1498235047194808320>|
|SATySFi|Tools/Libraries|Japanese|<https://twitter.com/i/communities/1498074334619123712>|
|Spring Developers|Tools/Libraries|English|<https://twitter.com/i/communities/1496544801533091844>|
|Svelte日本|Tools/Libraries|Japanese|<https://twitter.com/i/communities/1499182207491260424>|
|DATA Saber|Etc|Japanese|<https://twitter.com/i/communities/1498660583415361536>|
|IE11を偲ぶ会|Etc|Japanese|<https://twitter.com/i/communities/1498870842784043009>|
|ITエンジニアを褒める会|Etc|Japanese|<https://twitter.com/i/communities/1494319842585083906>|
|JMUG|Etc|Japanese|<https://twitter.com/i/communities/1498585537527320577>|
|Japan Okta User Group|Etc|Japanese|<https://twitter.com/i/communities/1498432461839036418>|
|SREとかObservabilityとか|Etc|Japanese|<https://twitter.com/i/communities/1498088713670172675>|
|Tech Twitter|Etc|English|<https://twitter.com/i/communities/1472105760389668865>|
|Tech Twitter - Japan|Etc|Japanese|<https://twitter.com/i/communities/1494649689215737856>|
|Twitter Developers Japan|Etc|Japanese|<https://twitter.com/i/communities/1493041080077795328>|
|UdonCreatorCommunity|Etc|Japanese|<https://twitter.com/i/communities/1497068375553765378>|
|nlp-jp|Etc|Japanese|<https://twitter.com/i/communities/1498287599928365062>|
|sudo-jp|Etc|Japanese|<https://twitter.com/i/communities/1499227044982374401>|
|ウェブパフォーマンス|Etc|Japanese|<https://twitter.com/i/communities/1498089387422515202>|
|ガジェット|Etc|Japanese|<https://twitter.com/i/communities/1498224086652121099>|
|ネットワーク自動化|Etc|Japanese|<https://twitter.com/i/communities/1498540422154821633>|
|バンクーバー日本人ソフトウェアエンジニア|Etc|Japanese|<https://twitter.com/i/communities/1498574247895056384>|
|吉祥寺.pm|Etc|Japanese|<https://twitter.com/i/communities/1498106494989967363>|
|日本のウェブフォームを良くする開発者の会|Etc|Japanese|<https://twitter.com/i/communities/1498168121336614916>|
|自作キーボード|Etc|Japanese|<https://twitter.com/i/communities/1495468692813287425>|
|鹿児島ITエンジニア|Etc|Japanese|<https://twitter.com/i/communities/1496763936682954752>|
Elixirのプログラム
lines =
File.read!("README.md")
|> String.split("\n")
fixed_contents_cnt =
lines
|> Enum.find_index(& &1 == "|-|-|-|-|")
|> Kernel.+(1)
table_contents =
lines
|> Enum.drop(fixed_contents_cnt)
|> Enum.reject(& &1 == "")
mapper = fn name, category, language, url ->
language = if language == "Japanese", do: "\u0000", else: language
if category == "Etc" do
{category, name, language, url, :etc}
else
{category, name, language, url}
end
end
sorted_table_contents =
table_contents
|> Enum.map(& {&1, String.split(&1, "|")})
|> Enum.sort_by(fn {_, ["", name, category, language, url, ""]} ->
mapper.(name, category, language, url)
end)
|> Enum.map(& elem(&1, 0))
Enum.take(lines, fixed_contents_cnt)
|> Kernel.++(sorted_table_contents)
|> Kernel.++([""])
|> Enum.join("\n")
|> then(&File.write!("README.md", &1))
FROM elixir:1.13.3-slim
WORKDIR /app
COPY . .
CMD ["elixir", "sort.exs"]
解説
少し解説をします。
Dockerfileは、Elixirを未インストールでも動かせるように用意しました。
Elixirをインストール済の方は気にしないでください。
このプログラムの肝はソートです。
Enum.sort_by/3を使いました。
この関数に指定するmapper
関数が肝です。
mapper
関数は、各要素どうしを何で比較するのかを返します。
もう一度仕様を記載します。
- テーブルの並び順は基本的に以下の順番とする
- Category順(UTF-8の文字列順)
- Name順(UTF-8の文字列順)
- Languageは
Japanese
を優先、他はUTF-8の文字列順 - URL順(UTF-8の文字列順)
- ただし、Category=Etcはテーブルの後方に置く
タプルを使って、比較したい順に要素を並べればよいです。
mapper = fn name, category, language, url ->
language = if language == "Japanese", do: "\u0000", else: language
if category == "Etc" do
{category, name, language, url, :etc}
else
{category, name, language, url}
end
end
例外部分については以下のように細工をしました。
「LanguageはJapanese
を優先、他はUTF-8の文字列順」については、Japanese
の場合にはNULL文字だけの文字列で置き換えることとしました。
NULL文字だけの文字列は、Elixirは以下のように書きます。
-
"\u0000"
もしくは <<0>>
(追記) 単純に空文字列 ""
でよいです。
「Category=Etcはテーブルの後方に置く」についてはタプルの要素を増やしておくことで後ろにまわすことにしました。
Elixirは、ソートをすっきり書けます。
動かし方
InputのREADME.md
を同じフォルダに置いておいてください。
docker build -t awesome-twitter-communities-sort .
docker run --rm -v "$PWD":/app awesome-twitter-communities-sort
もちろんElixirをインストール済の場合は以下のように実行できます。
elixir sort.exs
mattn/awesome-twitter-communities
Twitterのコミュニティのうち、技術系のコミュニティを @mattn さんがまとめてくださっています。
ありがとうございます!
たまに @mattn さんがソートコミットを入れられていたので、Elixirで書いてみたらどうなるのだろう? とおもって書いてみました。
きっとすでにツールはお持ちだったり、GitHub Actionsに自動ソートが組み込まれていいるのじゃないかとおもったりもしました。
せっかく作ったので、プルリクエストを送ってみました。
rejectされてもいいや〜 という気持ちです。
その旨、コメントに I don't mind
と書きました。
プルリクエストを送ったあとにすでに、@mattn さんのほうでGoのプログラムが作られていることに気づきました。
awesome-twitter-communities の並びを直すのが面倒になってきたのでツールをこさえた。https://t.co/I2BUdTiWcA
— mattn (@mattn_jp) March 4, 2022
それで、やっぱりプルリクエストはrejectでした
けれでも、Enum.sort_by/3に詳しくなれたし、Elixirは文字列操作がしやすいなあと感じられたので良かったです。
何よりも私は、Elixirを楽しめました。
何気に順番も大事で、
https://github.com/mattn/sort-awesome-twitter-communities/ リポジトリを先に見つけていたらElixirで作ることはしなかったかもしれません。
今回はソートがポイントだったのでやはり
$\huge{順番は大事💜}$
です。
mattn/awesome-twitter-communitiesにプルリクエストを送る際には、@mattn さんのsort-awesome-twitter-communities/でテーブルの行の並び替えを
$\huge{そ〜っと💜}$
しておくと良いとおもいます。
ソート
mattn/awesome-twitter-communitiesにformat-readme.cmd
と format-readme.sh
が追加されていました。
macOSで試しました。
./format-readme.sh
2022/03/05 12:12 adc0682では、Java
のところで差分がでました。
Languageのところをadc0682ではJapaneseが前にきていますが、スクリプトを実行するとEnglishが前にきます。
これはこんなところで言う話ではなくて、GitHubで言う話でしょうが、正解は作者の方の最新が正解ですので、特にアクションは起こしません。
この記事は架空のREADME.md
を題材とした話で、LanguageはJapanese
を優先ということをそのままにしておきます。
そのほうがプログラムに妙味がでるので。
git clone https://github.com/mattn/sort-awesome-twitter-communities
cd sort-awesome-twitter-communities
README.md
を同じフォルダに置いておいて
go main.go
Wrapping up
Enjoy Elixir
$\huge{Enjoy\ Elixir🚀}$
今回は、Enum.sort_by/3に指定するmapper
関数にて、並び替えたい優先度順に要素を並べておくだけで、複雑な並び替え仕様を簡単に実装できることを示しました。
mattn/awesome-twitter-communitiesにプルリクエストを送る際には、@mattn さんのsort-awesome-twitter-communities/でテーブルの行の並び替えを
$\huge{そ〜っと💜}$
しておくと良いとおもいます。
format-readme.sh
or format-readme.cmd
の実行を〜!!!
以上です。