{"id":13624059,"url":"https://github.com/akanehara/ginq","last_synced_at":"2025-04-15T20:33:08.329Z","repository":{"id":6175139,"uuid":"7405132","full_name":"akanehara/ginq","owner":"akanehara","description":"`LINQ to Object` inspired DSL for PHP","archived":false,"fork":false,"pushed_at":"2022-06-30T09:37:05.000Z","size":391,"stargazers_count":192,"open_issues_count":6,"forks_count":18,"subscribers_count":23,"default_branch":"master","last_synced_at":"2025-04-06T11:08:20.647Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akanehara.png","metadata":{"files":{"readme":"README.ja.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-01-02T10:25:35.000Z","updated_at":"2025-03-18T15:23:46.000Z","dependencies_parsed_at":"2022-07-18T08:13:19.971Z","dependency_job_id":null,"html_url":"https://github.com/akanehara/ginq","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akanehara%2Fginq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akanehara%2Fginq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akanehara%2Fginq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akanehara%2Fginq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akanehara","download_url":"https://codeload.github.com/akanehara/ginq/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249148289,"owners_count":21220510,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T21:01:38.372Z","updated_at":"2025-04-15T20:33:07.962Z","avatar_url":"https://github.com/akanehara.png","language":"PHP","funding_links":[],"categories":["数据结构和存储 Data Structure and Storage","目录","Table of Contents","PHP","Libraries"],"sub_categories":["数据结构和存储 Data Structure and Storage","Data Structure and Storage","[PHP](https://github.com/php/php-src)","Library"],"readme":"# Ginq\n\n### PHPの配列操作に幸せを！\n\n**Ginq** はPHPの配列やイテレータを統一的に（そのうえ楽しく！）操作するための **DSL** です。\n\n**Ginq** は **LINQ to Object** にインスパイアされましたが、クローンではありません。PHPの配列やイテレータの事情にできるだけ寄り添ってデザインされています。\n\n**Ginq** の多くの機能は、その結果を実際に取り出すまで処理を実行しません。この **遅延実行** という性質は、さまざまなメリットをもたらしてくれます。\n\n## 使い方\n\n```php\nrequire_once('Ginq.php');\n```\n\n**Ginq**をインポートします。\n\n```php\n$xs = Ginq::from(array(1,2,3,4,5,6,7,8,9,10))\n        -\u003ewhere(function($x) { return $x % 2 != 0; })\n        -\u003eselect(function($x) { return $x * $x; })\n        ;\n```\n\n**Ginq**にデータを渡して、クエリを組み立てます。\nここでは配列から偶数の要素だけを抽出して、されにそれを２乗しています。\n\nこの段階ではまだ **Ginq** は何もしません。 **「必要な結果は、元の配列を選択(where)・射影(select)したものである」** 、ということをGinqに伝えただけです。\n\n実際に **Ginq** を駆動して結果を得るために、`foreach`で **Ginq** を反復してみます。\n\n```php\nforeach ($xs in $x) { echo \"$x \"; }\n```\n\n```\n1 9 25 49 81\n```\n\n欲しい結果が得られました！\n\n今度は`toList()`を使って配列を得ましょう。\n\n```php\n$xs-\u003etoList();\n```\n\n```\narray(1,9,25,49,81);\n```\n\n**Ginq** には、ここで紹介した `select()`、`where()` 以外にも、`join()` `orderBy()` `groupBy()` のような、SQLでお馴染みの機能も備わっています。\n\n## セレクタと述語\n\n**Ginq** のほとんどのメソッドは、引数にクロージャをとります。\n\nクロージャと聞くと、使いなれない人はちょっと怯んでしまうかもしれませんが、実のところまったく難しくありません。**Ginq**が要求するクロージャのほとんどは **「述語」**  **「セレクタ」**  **「結合セレクタ」** のたったの３種類に分けられ、すぐに覚えられます！\n\n### 述語\n\n`where()` のような **選択** を行うメソッドに渡すクロージャを、**述語**（predicate）いいます。述語は要素のキーと値のペアをとり、条件を満たすかどうかを真理値で返す次のようなクロージャです。\n\n```php\nfunction ($v, [$k]) { return $v % 2 == 0; }\n```\n\nこのクロージャを`where()`に渡すと、クロージャの結果が`True`となるような要素、つまり偶数だけを選んで返してくれます。\n\nもしもキーに関心がないなら、第２引数を省略しても問題ありません。\n\n### セレクタ\n\n`select()` のような **射影** を行うメソッドに渡す関数を、**セレクタ** といいます。セレクタは要素のキーと値をのペアをとり、そこから新しい値（場面によってはキー）を作って返します。\n\n```php\nfunction ($v, [$k]) { return $v * $v ; }\n```\n\nこのクロージャを`select()`に渡すと、元の要素の値を２乗した並びが得られます。\n\nまた、射影という基本的な用途以外にも、`groupBy()`ではグループ化のキーを、`orderBy()`では並び替えのキーを指定するために使われます。\n\n### 結合セレクタ\n\n**結合セレクタ** は左右２つの要素を１つにまとめるセレクタの一種で、`join()` や `zip()` などで使われます。\n\n```php\nfunction ($v0, $v1, [$k0, $k1]) { return array($v0, $v1) ; }\n```\n\n左右２つの値と左右２つのキー、合計４つの引数をとり、それを使って新しい値（あるいはキー）を作って返します。\n\nもちろん、関心のない引数は省略しても大丈夫ですよ;-)\n\nさて、2つの並びを要素ごとに綴じ合わせる、`zip()`の例を見てみましょう。\n\n```php\n$foods  = array(\"お肉\", \"パスタ\", \"サラダ\");\n$spices = array(\"タイム\", \"バジル\", \"ディル\");\n\n$xs = Ginq::from($foods)\n        -\u003ezip($spices, function($f, $s) {\n            return \"$fに$s！\";\n        })\n        ;\n\nforeach ($xs in $x) { echo \"$x\\n\"; }\n```\n\n```\nお肉にタイム！\nパスタにバジル！\nサラダにティル！\n```\n\n## セレクタのショートカット\n\n**セレクタ** にかぎり、クロージャのかわりに文字列を渡すことができます。\n\n```php\nGinq::from($xs)-\u003eselect('[key].property');\n```\n\nは、\n\n```php\nGinq::from($xs)-\u003eselect(\n    function ($v, $k) { return $v['key']-\u003eproperty; }\n);\n```\n\nと同じ意味をもちます。\nこれはSymfonyのプロパディアクセスの記法に準じます。\n\nhttp://symfony.com/doc/current/components/property_access/index.html\n\n## もっと複雑な例\n\n## リファレンス\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakanehara%2Fginq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakanehara%2Fginq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakanehara%2Fginq/lists"}