{"id":18779382,"url":"https://github.com/zostay/raku-hash-multivalue","last_synced_at":"2025-10-03T22:17:47.597Z","repository":{"id":32923029,"uuid":"36518575","full_name":"zostay/raku-Hash-MultiValue","owner":"zostay","description":"Store multiple values per key, but act like a regular Hash too","archived":false,"fork":false,"pushed_at":"2020-02-08T16:36:04.000Z","size":43,"stargazers_count":2,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-04-12T11:04:05.208Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Raku","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"artistic-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zostay.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","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":"2015-05-29T17:20:23.000Z","updated_at":"2021-05-14T15:57:41.000Z","dependencies_parsed_at":"2022-08-02T00:59:46.718Z","dependency_job_id":null,"html_url":"https://github.com/zostay/raku-Hash-MultiValue","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zostay%2Fraku-Hash-MultiValue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zostay%2Fraku-Hash-MultiValue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zostay%2Fraku-Hash-MultiValue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zostay%2Fraku-Hash-MultiValue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zostay","download_url":"https://codeload.github.com/zostay/raku-Hash-MultiValue/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223583058,"owners_count":17168792,"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-11-07T20:19:53.741Z","updated_at":"2025-10-03T22:17:42.546Z","avatar_url":"https://github.com/zostay.png","language":"Raku","funding_links":[],"categories":[],"sub_categories":[],"readme":"NAME\n====\n\nHash::MultiValue - Store multiple values per key, but act like a regular hash too\n\nSYNOPSIS\n========\n\n    my %mv := Hash::MultiValue.from-pairs: (a =\u003e 1, b =\u003e 2, c =\u003e 3, a =\u003e 4);\n\n    say %mv\u003ca\u003e; # 4\n    say %mv\u003cb\u003e; # 2\n\n    say %mv('a').join(', '); # 1, 4\n    say %mv('b').join(', '); # 2\n\n    %mv\u003ca\u003e   = 5;\n    %mv\u003cd\u003e   = 6;\n    %mv('e') = 7, 8, 9;\n\n    say %mv.all-pairs».fmt(\"%s: %s\").join(\"\\n\");\n    # a: 5\n    # b: 2\n    # c: 3\n    # d: 6\n    # e: 7\n    # e: 8\n    # e: 9\n\nDESCRIPTION\n===========\n\nThis class is useful in cases where a program needs to have a hash that may or may not have multiple values per key, but frequently assumes only one value per key. This is commonly the case when dealing with URI query strings. This class also generally preserves the order the keys are encountered, which can also be a useful characteristic when working with query strings.\n\nIf some code is handed this object where a common [Associative](Associative) object (like a [Hash](Hash)) is expected, it will work as expected. Each value will only have a single value available. However, when one of these objects is used as function or using the various `.all-*` alternative methods, the full multi-valued contents of the keys can be fetched, modified, and iterated.\n\nThis class makes no guarantees to preserve the order of keys. However, the order of the multiple values stored within a key is guaranteed to be preserved. If you require key order to be preserved, you may want to look into [ArrayHash](ArrayHash) instead.\n\nMethods\n=======\n\nmethod new\n----------\n\n    multi method new(Hash::MultiValue:U:) returns Hash::MultiValue:D\n    multi method new(Hash::MultiValue:U: :@pairs!) returns Hash::MultiValue:D\n    multi method new(Hash::MultiValue:U: :@kv!) returns Hash::MultiValue:D\n    multi method new(Hash::MultiValue:U: :%mixed-hash!, :$iterate = Iterable, :\u0026iterator) returns Hash::MultiValue:D\n\nThis method constructs a multi-value hash. If called with no arguments, an empty hash will be constructed.\n\n    my %empty := Hash::MultiValue.new;\n\nIf called with the named `pairs` argument, then the given pairs will be used to instantiate the list. This is similar to calling `from-pairs` with the given list..\n\n    my %from-pairs := Hash::MultiValue.new(\n        pairs =\u003e (a =\u003e 1, b =\u003e 2, a =\u003e 3),\n    );\n\nIf called with the named `kv` argument, then the given list must have an even number of elements. The even-indexed items will be treated as keys, and the following odd-indexed items will be treated as the value for the preceding key. This is similar to calling `from-kv`.\n\n    my %from-kv = Hash::MultiValue.new(\n        kv =\u003e ('a', 1, 'b', 2, 'a', 3),\n    );\n\nIf called with the named `mixed-hash` argument, then the given hash will be treated as a mixed value hash. A mixed value hash is complicated, so using it to initialize this data structure is not ideal.\n\nIn order to initialize from such a structure, every value in the given hash must be evaluted by type. If the type of the value matches the one found in `$iterator` ([Iterable](Iterable) by default), then the key will be inserted multiple times, one for each item iterated. The iteration will be handled by just looping over the values using a `map` operation. You can provide your own `\u0026iterator` as well, which will be called for each value matching `$iterator`. The first argument will be key to return and the second will be the value that needs to be iterated. The `\u0026terator` should return a `Seq` of `Pair`s.\n\n    my %from-mixed := Hash::MultiValue.new(\n        mixed-hash =\u003e {\n            a =\u003e [ 1, 3 ],\n            b =\u003e 2,\n        },\n    );\n\nmethod from-pairs\n-----------------\n\n    method from-pairs(Hash::MultiValue:U: *@pairs) returns Hash::MultiValue:D\n\nThis takes a list of pairs and constructs a [Hash::MultiValue](Hash::MultiValue) object from it. Multiple pairs with the same key may be included in this list and all values will be associated with that key.\n\nIt should be noted that you may need to be a little careful with how you pass your pairs into this method. Perl 6 treats anything that looks like a named argument as a named argument. Here's a quick example of what works and what doesn't:\n\n    # THIS\n    my %h := Hash::MultiValue.from-pairs: (a =\u003e 1, b =\u003e 2, a =\u003e 3);\n    # OR THIS\n    my %h := Hash::MultiValue.from-pairs((a =\u003e 1, b =\u003e 2, a =\u003e 3));\n    # OR THIS\n    my %h := Hash::MultiValue.from-pairs('a' =\u003e 1, 'b' =\u003e 2, 'a' =\u003e 3);\n    # OR THIS\n    my @a := (a =\u003e 1, b =\u003e 2, a =\u003e 3);\n    my %h := Hash::MultiValue.from-pairs(@a);\n\n    # BUT NOT\n    my %h := Hash::MultiValue.from-pairs(a =\u003e 1, b =\u003e 2, a =\u003e 3);\n    # ALSO NOT\n    my %h := Hash::MultiValue.from-pairs(|@a);\n\nTo protect from accidentally passing these as named arguments, the method will fail if any named arguments are detected.\n\n### method from-pairs\n\n```perl6\nmethod from-pairs(\n    *@pairs,\n    *%badness\n) returns Hash::MultiValue:D\n```\n\nConstruct a Hash::MultiValue object from a list of pairs\n\nmethod from-kv\n--------------\n\n    method from-kv(Hash::MultiValue:U: +@kv) returns Hash::MultiValue:D\n\nThis takes a list of keys and values in a single list and turns them into pairs. The given list of items must have an even number of elements or the method will fail.\n\nThe even-indexed items will be treated as keys, and the following odd-indexed items will be treated as the value for the preceding key. This is similar to calling `from-kv`.\n\nmethod from-mixed-hash\n----------------------\n\n    multi method from-mixed-hash(Hash::MultiValue:U: %hash, :$iterate = Iterable, :\u0026iterate) returns Hash::MultiValue:D\n    multi method from-mixed-hash(Hash::MultiValue:U: *%hash) returns Hash::MultiValue:D\n\nThis takes a hash and constructs a new [Hash::MultiValue](Hash::MultiValue) from it as a mixed-value hash. A mixed value hash is complicated, so using it to initialize this data structure is not ideal.\n\nIn order to initialize from such a structure, every value in the given hash must be evaluted by type. If the type of the value matches the one found in `$iterator` ([Iterable](Iterable) by default), then the key will be inserted multiple times, one for each item iterated. The iteration will be handled by just looping over the values using a `map` operation. You can provide your own `\u0026iterator` as well, which will be called for each value matching `$iterator`. The first argument will be key to return and the second will be the value that needs to be iterated. The `\u0026terator` should return a `Seq` of `Pair`s.\n\n    my %from-mixed := Hash::MultiValue.from-mixed-hash(\n        a =\u003e [ 1, 3 ],\n        b =\u003e 2,\n    );\n\n    # The above is basically identical to:\n    # Hash::MultiValue.from-pairs: (a =\u003e 1, a =\u003e 3, b =\u003e 2);\n\n**Caution:** If you use the slurpy version of this method, you have no additional named options. Passing `iterate` or `iterator` will just result in those being put into the data structure.\n\n### multi method from-mixed-hash\n\n```perl6\nmulti method from-mixed-hash(\n    %mixed-hash,\n    :$iterate = Iterable,\n    :\u0026iterator = { ... }\n) returns Hash::MultiValue:D\n```\n\nConstruct a Hash::MultiValue object from a mixed value hash\n\n### multi method from-mixed-hash\n\n```perl6\nmulti method from-mixed-hash(\n    *%mixed-hash\n) returns Hash::MultiValue:D\n```\n\nConstruct a Hash::MultiValue object from a mixed value hash\n\nmethod postcircumfix:\u003c{ }\u003e\n--------------------------\n\n    method postcircumfix:\u003c{ }\u003e (Hash::MultiValue:D: %key) is rw\n\nWhenever reading or writing keys using the `{ }` operator, the hash will behave as a regular built-in [Hash](Hash). Any write will overwrite all values that have been set on the multi-value hash with a single value.\n\n    my %mv := Hash::MultiValue.from-pairs(a =\u003e 1, b =\u003e 2, a =\u003e 3);\n    %mv\u003ca\u003e = 4;\n    say %mv('a').join(', '); # 4\n\nAny read will only read a single value, even if multiple values are stored for that key.\n\n    my %mv := Hash::MultiValue.from-pairs(a =\u003e 1, b =\u003e 2, a =\u003e 3);\n    say %mv\u003ca\u003e; # 3\n\nOf those values the last value will always be used. This is in keeping with the usual semantics of what happens when you add two pairs with the same key twice in Perl 6.\n\nYou may also use the `:delete` and `:exists` adverbs with these objects.\n\n    my %mv := Hash::MultiValue.from-pairs(a =\u003e 1, b =\u003e 2, a =\u003e 3);\n    say %mv\u003ca\u003e :delete; # 3 (both 1 and 3 are gone)\n    say %mv\u003cb\u003e :exists; # True\n\nBinding is also supported. For example,\n\n    my $a = 4;\n    %mv\u003ca\u003e := $a;\n    $a = 5;\n    say %mv\u003ca\u003e; # 4\n\nmethod postcircumfix:\u003c( )\u003e\n--------------------------\n\n    method postcircumfix:\u003c( )\u003e (Hash::MultiValue:D: $key) is rw\n\nThe `( )` operator may be used in a fashion very similar to `{ }`, but in that it always works with multiple values. You may use it to read multiple values from the object:\n\n    my %mv := Hash::MultiValue.from-pairs(a =\u003e 1, b =\u003e 2, a =\u003e 3);\n    say %mv('a').join(', '); # 1, 3\n\nYou may also use it to write multiple values, which will replace all values currently set for that key:\n\n    my %mv := Hash::MultiValue.from-pairs(a =\u003e 1, b =\u003e 2, a =\u003e 3);\n    %mv('a') = 4, 5;\n    %mv('b') = 6, 7;\n    %mv('c') = 8;\n    say %mv('a').join(', '); # 4, 5\n    say %mv('b').join(', '); # 6, 7\n    say %mv('c').join(', '); # 8\n\nAt this time, this operator does not support slices (i.e., using a [Range](Range) or [List](List) of keys to get values for more than one key at once). This might be supported in the future.\n\nmethod kv\n---------\n\nReturns a list alternating between key and value. Each key will only be listed once with a singular value. See [/method all-kv](/method all-kv) for a multi-value version.\n\nmethod pairs\n------------\n\nReturns a list of [Pair](Pair) objects. Each key is returned just once pointing to the last (or only) value in the multi-value hash. See [/method all-pairs](/method all-pairs) for the multi-value version.\n\nmethod antipairs\n----------------\n\nThis is identical to [/method pairs](/method pairs), but with the value and keys swapped.\n\nmethod invert\n-------------\n\nThis is a synonym for [/method antipairs](/method antipairs).\n\nmethod keys\n-----------\n\nReturns a list of keys. Each key is returned exactly once. See [/method all-keys](/method all-keys) for the multi-value version.\n\nmethod values\n-------------\n\nReturns a list of values. Only the last value of a multi-value key is returned. See [/method all-values](/method all-values) for the multi-value version.\n\nmethod all-kv\n-------------\n\nReturns a list alternating between key and value. Multi-value key will be listed more than once.\n\nmethod all-pairs\n----------------\n\nReturns a list of [Pair](Pair) objects. Multi-value keys will be returned multiple times, once for each value associated with the key.\n\nmethod all-antipairs\n--------------------\n\nThis is identical to [/method all-pairs](/method all-pairs), but with key and value reversed.\n\nmethod all-invert\n-----------------\n\nThis is a synonym for [/method all-antipairs](/method all-antipairs).\n\nmethod keys\n-----------\n\nThis returns a list of keys. Multi-valued keys will be returned more than once. If you want the unique key list, you want to see [/method keys](/method keys).\n\nmethod values\n-------------\n\nThis returns a list of all values, including the multiple values on a single key.\n\nmethod push\n-----------\n\n    method push(*@values)\n\nThis adds new pairs to the list. Any pairs given with a key matching an existing key will cause the single value version of that key to be replaced with the new value. This never overwrites existing values.\n\nmethod perl\n-----------\n\nReturns code as a string that can be evaluated with `EVAL` to recreate the object.\n\nmethod gist\n-----------\n\nLike [/method perl](/method perl), but only includes up to the first 100 keys.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzostay%2Fraku-hash-multivalue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzostay%2Fraku-hash-multivalue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzostay%2Fraku-hash-multivalue/lists"}