hamster 1.0.1.pre.rc3 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/hamster.rb +2 -0
- data/lib/hamster/associable.rb +49 -0
- data/lib/hamster/core_ext/enumerable.rb +3 -13
- data/lib/hamster/core_ext/io.rb +1 -1
- data/lib/hamster/core_ext/struct.rb +9 -0
- data/lib/hamster/deque.rb +57 -38
- data/lib/hamster/enumerable.rb +14 -41
- data/lib/hamster/experimental/mutable_queue.rb +5 -8
- data/lib/hamster/experimental/mutable_set.rb +6 -7
- data/lib/hamster/hash.rb +301 -110
- data/lib/hamster/immutable.rb +1 -1
- data/lib/hamster/list.rb +479 -194
- data/lib/hamster/mutable_hash.rb +6 -7
- data/lib/hamster/nested.rb +78 -0
- data/lib/hamster/read_copy_update.rb +1 -1
- data/lib/hamster/set.rb +198 -88
- data/lib/hamster/sorted_set.rb +706 -261
- data/lib/hamster/trie.rb +134 -15
- data/lib/hamster/vector.rb +571 -140
- data/lib/hamster/version.rb +3 -1
- data/spec/lib/hamster/associable/associable_spec.rb +150 -0
- data/spec/lib/hamster/core_ext/array_spec.rb +1 -1
- data/spec/lib/hamster/core_ext/enumerable_spec.rb +2 -2
- data/spec/lib/hamster/core_ext/io_spec.rb +1 -1
- data/spec/lib/hamster/deque/clear_spec.rb +3 -3
- data/spec/lib/hamster/deque/construction_spec.rb +8 -8
- data/spec/lib/hamster/deque/copying_spec.rb +1 -1
- data/spec/lib/hamster/deque/dequeue_spec.rb +12 -4
- data/spec/lib/hamster/deque/empty_spec.rb +14 -16
- data/spec/lib/hamster/deque/enqueue_spec.rb +4 -4
- data/spec/lib/hamster/deque/first_spec.rb +18 -0
- data/spec/lib/hamster/deque/inspect_spec.rb +1 -1
- data/spec/lib/hamster/deque/last_spec.rb +9 -11
- data/spec/lib/hamster/deque/marshal_spec.rb +6 -6
- data/spec/lib/hamster/deque/new_spec.rb +5 -5
- data/spec/lib/hamster/deque/pop_spec.rb +15 -3
- data/spec/lib/hamster/deque/pretty_print_spec.rb +24 -0
- data/spec/lib/hamster/deque/push_spec.rb +37 -0
- data/spec/lib/hamster/deque/shift_spec.rb +30 -0
- data/spec/lib/hamster/deque/size_spec.rb +1 -1
- data/spec/lib/hamster/deque/to_a_spec.rb +2 -2
- data/spec/lib/hamster/deque/to_ary_spec.rb +1 -1
- data/spec/lib/hamster/deque/to_list_spec.rb +3 -3
- data/spec/lib/hamster/deque/unshift_spec.rb +8 -3
- data/spec/lib/hamster/experimental/mutable_set/add_qm_spec.rb +3 -3
- data/spec/lib/hamster/experimental/mutable_set/add_spec.rb +3 -3
- data/spec/lib/hamster/experimental/mutable_set/delete_qm_spec.rb +3 -3
- data/spec/lib/hamster/experimental/mutable_set/delete_spec.rb +3 -3
- data/spec/lib/hamster/hash/all_spec.rb +32 -34
- data/spec/lib/hamster/hash/any_spec.rb +34 -36
- data/spec/lib/hamster/hash/assoc_spec.rb +3 -3
- data/spec/lib/hamster/hash/clear_spec.rb +4 -4
- data/spec/lib/hamster/hash/construction_spec.rb +8 -8
- data/spec/lib/hamster/hash/copying_spec.rb +1 -1
- data/spec/lib/hamster/hash/default_proc_spec.rb +3 -3
- data/spec/lib/hamster/hash/delete_spec.rb +4 -4
- data/spec/lib/hamster/hash/each_spec.rb +3 -3
- data/spec/lib/hamster/hash/each_with_index_spec.rb +1 -1
- data/spec/lib/hamster/hash/empty_spec.rb +13 -15
- data/spec/lib/hamster/hash/eql_spec.rb +4 -4
- data/spec/lib/hamster/hash/except_spec.rb +7 -7
- data/spec/lib/hamster/hash/fetch_spec.rb +10 -10
- data/spec/lib/hamster/hash/find_spec.rb +2 -2
- data/spec/lib/hamster/hash/flat_map_spec.rb +4 -4
- data/spec/lib/hamster/hash/flatten_spec.rb +13 -13
- data/spec/lib/hamster/hash/get_spec.rb +7 -7
- data/spec/lib/hamster/hash/has_key_spec.rb +3 -3
- data/spec/lib/hamster/hash/has_value_spec.rb +4 -4
- data/spec/lib/hamster/hash/hash_spec.rb +5 -5
- data/spec/lib/hamster/hash/inspect_spec.rb +2 -2
- data/spec/lib/hamster/hash/invert_spec.rb +6 -6
- data/spec/lib/hamster/hash/key_spec.rb +2 -2
- data/spec/lib/hamster/hash/keys_spec.rb +2 -2
- data/spec/lib/hamster/hash/map_spec.rb +4 -4
- data/spec/lib/hamster/hash/marshal_spec.rb +2 -2
- data/spec/lib/hamster/hash/merge_spec.rb +62 -56
- data/spec/lib/hamster/hash/min_max_spec.rb +9 -13
- data/spec/lib/hamster/hash/new_spec.rb +6 -6
- data/spec/lib/hamster/hash/none_spec.rb +3 -3
- data/spec/lib/hamster/hash/partition_spec.rb +2 -2
- data/spec/lib/hamster/hash/put_spec.rb +29 -7
- data/spec/lib/hamster/hash/reduce_spec.rb +4 -4
- data/spec/lib/hamster/hash/{remove_spec.rb → reject_spec.rb} +7 -7
- data/spec/lib/hamster/hash/reverse_each_spec.rb +1 -1
- data/spec/lib/hamster/hash/{filter_spec.rb → select_spec.rb} +6 -6
- data/spec/lib/hamster/hash/size_spec.rb +3 -3
- data/spec/lib/hamster/hash/slice_spec.rb +4 -4
- data/spec/lib/hamster/hash/sort_spec.rb +2 -2
- data/spec/lib/hamster/hash/store_spec.rb +29 -7
- data/spec/lib/hamster/hash/take_spec.rb +2 -2
- data/spec/lib/hamster/hash/to_a_spec.rb +1 -1
- data/spec/lib/hamster/hash/to_hash_spec.rb +4 -4
- data/spec/lib/hamster/hash/values_at_spec.rb +3 -3
- data/spec/lib/hamster/hash/values_spec.rb +2 -2
- data/spec/lib/hamster/immutable/new_spec.rb +14 -0
- data/spec/lib/hamster/list/add_spec.rb +16 -10
- data/spec/lib/hamster/list/all_spec.rb +33 -35
- data/spec/lib/hamster/list/any_spec.rb +29 -31
- data/spec/lib/hamster/list/append_spec.rb +6 -6
- data/spec/lib/hamster/list/at_spec.rb +1 -1
- data/spec/lib/hamster/list/break_spec.rb +4 -4
- data/spec/lib/hamster/list/cadr_spec.rb +9 -9
- data/spec/lib/hamster/list/chunk_spec.rb +5 -5
- data/spec/lib/hamster/list/clear_spec.rb +3 -3
- data/spec/lib/hamster/list/combination_spec.rb +3 -3
- data/spec/lib/hamster/list/compact_spec.rb +3 -3
- data/spec/lib/hamster/list/compare_spec.rb +3 -3
- data/spec/lib/hamster/list/cons_spec.rb +15 -17
- data/spec/lib/hamster/list/construction_spec.rb +20 -27
- data/spec/lib/hamster/list/copying_spec.rb +1 -1
- data/spec/lib/hamster/list/count_spec.rb +1 -1
- data/spec/lib/hamster/list/cycle_spec.rb +4 -4
- data/spec/lib/hamster/list/delete_at_spec.rb +4 -4
- data/spec/lib/hamster/list/drop_spec.rb +3 -3
- data/spec/lib/hamster/list/drop_while_spec.rb +3 -3
- data/spec/lib/hamster/list/each_slice_spec.rb +5 -5
- data/spec/lib/hamster/list/each_spec.rb +26 -28
- data/spec/lib/hamster/list/each_with_index_spec.rb +1 -1
- data/spec/lib/hamster/list/empty_spec.rb +13 -15
- data/spec/lib/hamster/list/eql_spec.rb +21 -21
- data/spec/lib/hamster/list/fill_spec.rb +8 -8
- data/spec/lib/hamster/list/find_all_spec.rb +3 -3
- data/spec/lib/hamster/list/find_index_spec.rb +1 -1
- data/spec/lib/hamster/list/find_spec.rb +1 -1
- data/spec/lib/hamster/list/flat_map_spec.rb +2 -2
- data/spec/lib/hamster/list/flatten_spec.rb +5 -5
- data/spec/lib/hamster/list/grep_spec.rb +4 -4
- data/spec/lib/hamster/list/group_by_spec.rb +6 -6
- data/spec/lib/hamster/list/hash_spec.rb +2 -2
- data/spec/lib/hamster/list/head_spec.rb +1 -1
- data/spec/lib/hamster/list/include_spec.rb +2 -2
- data/spec/lib/hamster/list/index_spec.rb +38 -0
- data/spec/lib/hamster/list/indices_spec.rb +62 -0
- data/spec/lib/hamster/list/init_spec.rb +3 -3
- data/spec/lib/hamster/list/inits_spec.rb +3 -3
- data/spec/lib/hamster/list/insert_spec.rb +1 -1
- data/spec/lib/hamster/list/inspect_spec.rb +1 -1
- data/spec/lib/hamster/list/intersperse_spec.rb +3 -3
- data/spec/lib/hamster/list/join_spec.rb +5 -5
- data/spec/lib/hamster/list/last_spec.rb +1 -1
- data/spec/lib/hamster/list/ltlt_spec.rb +20 -0
- data/spec/lib/hamster/list/map_spec.rb +4 -4
- data/spec/lib/hamster/list/maximum_spec.rb +24 -26
- data/spec/lib/hamster/list/merge_by_spec.rb +10 -10
- data/spec/lib/hamster/list/merge_spec.rb +10 -10
- data/spec/lib/hamster/list/minimum_spec.rb +24 -26
- data/spec/lib/hamster/list/multithreading_spec.rb +6 -6
- data/spec/lib/hamster/list/none_spec.rb +5 -5
- data/spec/lib/hamster/list/one_spec.rb +5 -5
- data/spec/lib/hamster/list/partition_spec.rb +8 -8
- data/spec/lib/hamster/list/permutation_spec.rb +8 -8
- data/spec/lib/hamster/list/pop_spec.rb +3 -3
- data/spec/lib/hamster/list/product_spec.rb +1 -1
- data/spec/lib/hamster/list/reduce_spec.rb +5 -48
- data/spec/lib/hamster/list/{remove_spec.rb → reject_spec.rb} +4 -4
- data/spec/lib/hamster/list/reverse_spec.rb +3 -3
- data/spec/lib/hamster/list/rotate_spec.rb +7 -7
- data/spec/lib/hamster/list/sample_spec.rb +1 -1
- data/spec/lib/hamster/list/select_spec.rb +3 -3
- data/spec/lib/hamster/list/size_spec.rb +1 -1
- data/spec/lib/hamster/list/slice_spec.rb +123 -123
- data/spec/lib/hamster/list/sorting_spec.rb +5 -5
- data/spec/lib/hamster/list/span_spec.rb +5 -5
- data/spec/lib/hamster/list/split_at_spec.rb +4 -4
- data/spec/lib/hamster/list/subsequences_spec.rb +1 -1
- data/spec/lib/hamster/list/sum_spec.rb +1 -1
- data/spec/lib/hamster/list/tail_spec.rb +4 -4
- data/spec/lib/hamster/list/tails_spec.rb +3 -3
- data/spec/lib/hamster/list/take_spec.rb +3 -3
- data/spec/lib/hamster/list/take_while_spec.rb +4 -4
- data/spec/lib/hamster/list/to_a_spec.rb +2 -2
- data/spec/lib/hamster/list/to_ary_spec.rb +1 -1
- data/spec/lib/hamster/list/to_list_spec.rb +1 -1
- data/spec/lib/hamster/list/to_set_spec.rb +1 -1
- data/spec/lib/hamster/list/union_spec.rb +4 -4
- data/spec/lib/hamster/list/uniq_spec.rb +23 -19
- data/spec/lib/hamster/list/zip_spec.rb +5 -5
- data/spec/lib/hamster/nested/construction_spec.rb +103 -0
- data/spec/lib/hamster/set/add_spec.rb +13 -11
- data/spec/lib/hamster/set/all_spec.rb +32 -34
- data/spec/lib/hamster/set/any_spec.rb +32 -34
- data/spec/lib/hamster/set/clear_spec.rb +3 -3
- data/spec/lib/hamster/set/compact_spec.rb +3 -3
- data/spec/lib/hamster/set/construction_spec.rb +3 -3
- data/spec/lib/hamster/set/copying_spec.rb +1 -1
- data/spec/lib/hamster/set/count_spec.rb +1 -1
- data/spec/lib/hamster/set/delete_spec.rb +8 -8
- data/spec/lib/hamster/set/difference_spec.rb +8 -8
- data/spec/lib/hamster/set/disjoint_spec.rb +1 -1
- data/spec/lib/hamster/set/each_spec.rb +2 -2
- data/spec/lib/hamster/set/empty_spec.rb +15 -17
- data/spec/lib/hamster/set/eqeq_spec.rb +3 -3
- data/spec/lib/hamster/set/eql_spec.rb +3 -3
- data/spec/lib/hamster/set/exclusion_spec.rb +7 -7
- data/spec/lib/hamster/set/find_spec.rb +2 -2
- data/spec/lib/hamster/set/first_spec.rb +29 -0
- data/spec/lib/hamster/set/flatten_spec.rb +9 -9
- data/spec/lib/hamster/set/grep_spec.rb +1 -1
- data/spec/lib/hamster/set/group_by_spec.rb +12 -12
- data/spec/lib/hamster/set/hash_spec.rb +3 -3
- data/spec/lib/hamster/set/include_spec.rb +8 -8
- data/spec/lib/hamster/set/inspect_spec.rb +2 -2
- data/spec/lib/hamster/set/intersect_spec.rb +1 -1
- data/spec/lib/hamster/set/intersection_spec.rb +13 -13
- data/spec/lib/hamster/set/join_spec.rb +6 -6
- data/spec/lib/hamster/set/map_spec.rb +7 -7
- data/spec/lib/hamster/set/marshal_spec.rb +2 -2
- data/spec/lib/hamster/set/maximum_spec.rb +22 -24
- data/spec/lib/hamster/set/minimum_spec.rb +22 -24
- data/spec/lib/hamster/set/new_spec.rb +5 -5
- data/spec/lib/hamster/set/none_spec.rb +5 -5
- data/spec/lib/hamster/set/one_spec.rb +6 -6
- data/spec/lib/hamster/set/partition_spec.rb +5 -5
- data/spec/lib/hamster/set/product_spec.rb +2 -2
- data/spec/lib/hamster/set/reduce_spec.rb +5 -5
- data/spec/lib/hamster/set/{remove_spec.rb → reject_spec.rb} +6 -6
- data/spec/lib/hamster/set/reverse_each_spec.rb +1 -1
- data/spec/lib/hamster/set/sample_spec.rb +1 -1
- data/spec/lib/hamster/set/{filter_spec.rb → select_spec.rb} +11 -11
- data/spec/lib/hamster/set/size_spec.rb +1 -1
- data/spec/lib/hamster/set/sorting_spec.rb +16 -5
- data/spec/lib/hamster/set/subset_spec.rb +2 -2
- data/spec/lib/hamster/set/sum_spec.rb +2 -2
- data/spec/lib/hamster/set/superset_spec.rb +2 -2
- data/spec/lib/hamster/set/to_a_spec.rb +2 -2
- data/spec/lib/hamster/set/to_list_spec.rb +2 -2
- data/spec/lib/hamster/set/to_set_spec.rb +1 -1
- data/spec/lib/hamster/set/union_spec.rb +23 -14
- data/spec/lib/hamster/sorted_set/above_spec.rb +11 -11
- data/spec/lib/hamster/sorted_set/add_spec.rb +8 -8
- data/spec/lib/hamster/sorted_set/at_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/below_spec.rb +11 -11
- data/spec/lib/hamster/sorted_set/between_spec.rb +11 -11
- data/spec/lib/hamster/sorted_set/clear_spec.rb +11 -2
- data/spec/lib/hamster/sorted_set/copying_spec.rb +21 -0
- data/spec/lib/hamster/sorted_set/delete_at_spec.rb +4 -4
- data/spec/lib/hamster/sorted_set/delete_spec.rb +21 -12
- data/spec/lib/hamster/sorted_set/difference_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/disjoint_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/drop_spec.rb +30 -3
- data/spec/lib/hamster/sorted_set/drop_while_spec.rb +4 -4
- data/spec/lib/hamster/sorted_set/each_spec.rb +16 -18
- data/spec/lib/hamster/sorted_set/empty_spec.rb +12 -14
- data/spec/lib/hamster/sorted_set/eql_spec.rb +5 -5
- data/spec/lib/hamster/sorted_set/exclusion_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/fetch_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/find_index_spec.rb +10 -2
- data/spec/lib/hamster/sorted_set/first_spec.rb +10 -12
- data/spec/lib/hamster/sorted_set/from_spec.rb +11 -11
- data/spec/lib/hamster/sorted_set/group_by_spec.rb +10 -10
- data/spec/lib/hamster/sorted_set/include_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/inspect_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/intersect_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/intersection_spec.rb +3 -3
- data/spec/lib/hamster/sorted_set/last_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/map_spec.rb +13 -5
- data/spec/lib/hamster/sorted_set/marshal_spec.rb +3 -3
- data/spec/lib/hamster/sorted_set/maximum_spec.rb +37 -0
- data/spec/lib/hamster/sorted_set/minimum_spec.rb +11 -13
- data/spec/lib/hamster/sorted_set/new_spec.rb +23 -3
- data/spec/lib/hamster/sorted_set/reverse_each_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/{filter_spec.rb → select_spec.rb} +10 -10
- data/spec/lib/hamster/sorted_set/size_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/slice_spec.rb +158 -142
- data/spec/lib/hamster/sorted_set/sorting_spec.rb +3 -3
- data/spec/lib/hamster/sorted_set/subset_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/superset_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/take_spec.rb +32 -3
- data/spec/lib/hamster/sorted_set/take_while_spec.rb +4 -4
- data/spec/lib/hamster/sorted_set/to_set_spec.rb +1 -1
- data/spec/lib/hamster/sorted_set/union_spec.rb +2 -2
- data/spec/lib/hamster/sorted_set/up_to_spec.rb +12 -11
- data/spec/lib/hamster/sorted_set/values_at_spec.rb +6 -6
- data/spec/lib/hamster/vector/add_spec.rb +3 -3
- data/spec/lib/hamster/vector/any_spec.rb +1 -1
- data/spec/lib/hamster/vector/assoc_spec.rb +11 -1
- data/spec/lib/hamster/vector/bsearch_spec.rb +10 -2
- data/spec/lib/hamster/vector/clear_spec.rb +3 -3
- data/spec/lib/hamster/vector/combination_spec.rb +4 -4
- data/spec/lib/hamster/vector/compact_spec.rb +2 -2
- data/spec/lib/hamster/vector/compare_spec.rb +3 -3
- data/spec/lib/hamster/vector/concat_spec.rb +2 -2
- data/spec/lib/hamster/vector/copying_spec.rb +1 -1
- data/spec/lib/hamster/vector/delete_at_spec.rb +8 -8
- data/spec/lib/hamster/vector/delete_spec.rb +2 -2
- data/spec/lib/hamster/vector/drop_spec.rb +10 -3
- data/spec/lib/hamster/vector/drop_while_spec.rb +5 -5
- data/spec/lib/hamster/vector/each_index_spec.rb +2 -2
- data/spec/lib/hamster/vector/each_spec.rb +27 -29
- data/spec/lib/hamster/vector/each_with_index_spec.rb +2 -2
- data/spec/lib/hamster/vector/empty_spec.rb +11 -13
- data/spec/lib/hamster/vector/eql_spec.rb +6 -6
- data/spec/lib/hamster/vector/fetch_spec.rb +1 -1
- data/spec/lib/hamster/vector/fill_spec.rb +9 -9
- data/spec/lib/hamster/vector/first_spec.rb +10 -12
- data/spec/lib/hamster/vector/flat_map_spec.rb +51 -0
- data/spec/lib/hamster/vector/flatten_spec.rb +15 -0
- data/spec/lib/hamster/vector/get_spec.rb +4 -4
- data/spec/lib/hamster/vector/group_by_spec.rb +12 -12
- data/spec/lib/hamster/vector/include_spec.rb +2 -2
- data/spec/lib/hamster/vector/insert_spec.rb +2 -2
- data/spec/lib/hamster/vector/inspect_spec.rb +1 -1
- data/spec/lib/hamster/vector/join_spec.rb +5 -5
- data/spec/lib/hamster/vector/last_spec.rb +1 -1
- data/spec/lib/hamster/vector/length_spec.rb +1 -1
- data/spec/lib/hamster/vector/ltlt_spec.rb +2 -2
- data/spec/lib/hamster/vector/map_spec.rb +5 -5
- data/spec/lib/hamster/vector/marshal_spec.rb +2 -2
- data/spec/lib/hamster/vector/maximum_spec.rb +20 -22
- data/spec/lib/hamster/vector/minimum_spec.rb +20 -22
- data/spec/lib/hamster/vector/multiply_spec.rb +4 -4
- data/spec/lib/hamster/vector/partition_spec.rb +5 -5
- data/spec/lib/hamster/vector/permutation_spec.rb +4 -4
- data/spec/lib/hamster/vector/pop_spec.rb +3 -3
- data/spec/lib/hamster/vector/product_spec.rb +10 -10
- data/spec/lib/hamster/vector/put_spec.rb +175 -0
- data/spec/lib/hamster/vector/reduce_spec.rb +5 -57
- data/spec/lib/hamster/vector/{remove_spec.rb → reject_spec.rb} +4 -4
- data/spec/lib/hamster/vector/repeated_combination_spec.rb +4 -4
- data/spec/lib/hamster/vector/repeated_permutation_spec.rb +6 -6
- data/spec/lib/hamster/vector/reverse_each_spec.rb +1 -1
- data/spec/lib/hamster/vector/reverse_spec.rb +1 -1
- data/spec/lib/hamster/vector/rindex_spec.rb +1 -1
- data/spec/lib/hamster/vector/rotate_spec.rb +9 -9
- data/spec/lib/hamster/vector/sample_spec.rb +1 -1
- data/spec/lib/hamster/vector/{filter_spec.rb → select_spec.rb} +8 -8
- data/spec/lib/hamster/vector/set_spec.rb +12 -141
- data/spec/lib/hamster/vector/shift_spec.rb +3 -3
- data/spec/lib/hamster/vector/shuffle_spec.rb +2 -2
- data/spec/lib/hamster/vector/slice_spec.rb +137 -137
- data/spec/lib/hamster/vector/sorting_spec.rb +5 -5
- data/spec/lib/hamster/vector/sum_spec.rb +1 -1
- data/spec/lib/hamster/vector/take_spec.rb +17 -3
- data/spec/lib/hamster/vector/take_while_spec.rb +4 -4
- data/spec/lib/hamster/vector/to_a_spec.rb +1 -1
- data/spec/lib/hamster/vector/to_ary_spec.rb +1 -1
- data/spec/lib/hamster/vector/to_list_spec.rb +2 -1
- data/spec/lib/hamster/vector/to_set_spec.rb +1 -1
- data/spec/lib/hamster/vector/uniq_spec.rb +27 -6
- data/spec/lib/hamster/vector/unshift_spec.rb +3 -3
- data/spec/lib/hamster/vector/values_at_spec.rb +6 -6
- data/spec/lib/hamster/vector/zip_spec.rb +2 -2
- data/spec/lib/load_spec.rb +42 -0
- data/spec/spec_helper.rb +25 -0
- metadata +85 -48
- data/spec/lib/hamster/deque/head_spec.rb +0 -20
- data/spec/lib/hamster/hash/uniq_spec.rb +0 -14
- data/spec/lib/hamster/list/elem_index_spec.rb +0 -36
- data/spec/lib/hamster/list/elem_indices_spec.rb +0 -31
- data/spec/lib/hamster/list/filter_spec.rb +0 -71
- data/spec/lib/hamster/list/find_indices_spec.rb +0 -37
- data/spec/lib/hamster/set/foreach_spec.rb +0 -40
- data/spec/lib/hamster/set/head_spec.rb +0 -31
- data/spec/lib/hamster/set/uniq_spec.rb +0 -14
- data/spec/lib/hamster/sorted_set/construction_spec.rb +0 -29
- data/spec/lib/hamster/vector/exist_spec.rb +0 -70
- data/spec/lib/hamster/vector/exists_spec.rb +0 -70
data/lib/hamster/trie.rb
CHANGED
@@ -29,7 +29,15 @@ module Hamster
|
|
29
29
|
|
30
30
|
# Calls <tt>block</tt> once for each entry in the trie, passing the key-value pair as parameters.
|
31
31
|
def each(&block)
|
32
|
-
|
32
|
+
# TODO: Using block.call here is slower than using yield by 5-10%, but
|
33
|
+
# the latter segfaults on ruby 2.2 and above. Once that is fixed and
|
34
|
+
# broken versions are sufficiently old, we should revert back to yield
|
35
|
+
# with a warning that the broken versions are unsupported.
|
36
|
+
#
|
37
|
+
# For more context:
|
38
|
+
# * https://bugs.ruby-lang.org/issues/11451
|
39
|
+
# * https://github.com/hamstergem/hamster/issues/189
|
40
|
+
@entries.each { |entry| block.call(entry) if entry }
|
33
41
|
@children.each do |child|
|
34
42
|
child.each(&block) if child
|
35
43
|
end
|
@@ -49,11 +57,15 @@ module Hamster
|
|
49
57
|
memo
|
50
58
|
end
|
51
59
|
|
52
|
-
def
|
53
|
-
|
60
|
+
def select
|
61
|
+
keys_to_delete = []
|
62
|
+
each { |entry| keys_to_delete << entry[0] unless yield(entry) }
|
63
|
+
bulk_delete(keys_to_delete)
|
54
64
|
end
|
55
65
|
|
56
|
-
#
|
66
|
+
# @return [Trie] A copy of `self` with the given value associated with the
|
67
|
+
# key (or `self` if no modification was needed because an identical
|
68
|
+
# key-value pair wes already stored
|
57
69
|
def put(key, value)
|
58
70
|
index = index_for(key)
|
59
71
|
entry = @entries[index]
|
@@ -64,22 +76,81 @@ module Hamster
|
|
64
76
|
entries[index] = [key, value].freeze
|
65
77
|
Trie.new(@significant_bits, @size + 1, entries, @children)
|
66
78
|
elsif entry[0].eql?(key)
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
79
|
+
if entry[1].equal?(value)
|
80
|
+
self
|
81
|
+
else
|
82
|
+
entries = @entries.dup
|
83
|
+
key = key.dup.freeze if key.is_a?(String) && !key.frozen?
|
84
|
+
entries[index] = [key, value].freeze
|
85
|
+
Trie.new(@significant_bits, @size, entries, @children)
|
86
|
+
end
|
71
87
|
else
|
72
|
-
|
73
|
-
child = children[index]
|
74
|
-
child_size = child ? child.size : 0
|
88
|
+
child = @children[index]
|
75
89
|
if child
|
76
|
-
|
90
|
+
new_child = child.put(key, value)
|
91
|
+
if new_child.equal?(child)
|
92
|
+
self
|
93
|
+
else
|
94
|
+
children = @children.dup
|
95
|
+
children[index] = new_child
|
96
|
+
new_self_size = @size + (new_child.size - child.size)
|
97
|
+
Trie.new(@significant_bits, new_self_size, @entries, children)
|
98
|
+
end
|
77
99
|
else
|
100
|
+
children = @children.dup
|
78
101
|
children[index] = Trie.new(@significant_bits + 5).put!(key, value)
|
102
|
+
Trie.new(@significant_bits, @size + 1, @entries, children)
|
79
103
|
end
|
80
|
-
|
81
|
-
|
82
|
-
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Put multiple elements into a Trie. This is more efficient than several
|
108
|
+
# calls to `#put`.
|
109
|
+
#
|
110
|
+
# @param key_value_pairs Enumerable of pairs (`[key, value]`)
|
111
|
+
# @return [Trie] A copy of `self` after associated the given keys and
|
112
|
+
# values (or `self` if no modifications where needed).
|
113
|
+
def bulk_put(key_value_pairs)
|
114
|
+
new_entries = nil
|
115
|
+
new_children = nil
|
116
|
+
new_size = @size
|
117
|
+
|
118
|
+
key_value_pairs.each do |key, value|
|
119
|
+
index = index_for(key)
|
120
|
+
entry = (new_entries || @entries)[index]
|
121
|
+
|
122
|
+
if !entry
|
123
|
+
new_entries ||= @entries.dup
|
124
|
+
key = key.dup.freeze if key.is_a?(String) && !key.frozen?
|
125
|
+
new_entries[index] = [key, value].freeze
|
126
|
+
new_size += 1
|
127
|
+
elsif entry[0].eql?(key)
|
128
|
+
if !entry[1].equal?(value)
|
129
|
+
new_entries ||= @entries.dup
|
130
|
+
key = key.dup.freeze if key.is_a?(String) && !key.frozen?
|
131
|
+
new_entries[index] = [key, value].freeze
|
132
|
+
end
|
133
|
+
else
|
134
|
+
child = (new_children || @children)[index]
|
135
|
+
if child
|
136
|
+
new_child = child.put(key, value)
|
137
|
+
if !new_child.equal?(child)
|
138
|
+
new_children ||= @children.dup
|
139
|
+
new_children[index] = new_child
|
140
|
+
new_size += new_child.size - child.size
|
141
|
+
end
|
142
|
+
else
|
143
|
+
new_children ||= @children.dup
|
144
|
+
new_children[index] = Trie.new(@significant_bits + 5).put!(key, value)
|
145
|
+
new_size += 1
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
if new_entries || new_children
|
151
|
+
Trie.new(@significant_bits, new_size, new_entries || @entries, new_children || @children)
|
152
|
+
else
|
153
|
+
self
|
83
154
|
end
|
84
155
|
end
|
85
156
|
|
@@ -125,6 +196,54 @@ module Hamster
|
|
125
196
|
find_and_delete(key) || Trie.new(@significant_bits)
|
126
197
|
end
|
127
198
|
|
199
|
+
# Delete multiple elements from a Trie. This is more efficient than
|
200
|
+
# several calls to `#delete`.
|
201
|
+
#
|
202
|
+
# @param keys [Enumerable] The keys to delete
|
203
|
+
# @return [Trie]
|
204
|
+
def bulk_delete(keys)
|
205
|
+
new_entries = nil
|
206
|
+
new_children = nil
|
207
|
+
new_size = @size
|
208
|
+
|
209
|
+
keys.each do |key|
|
210
|
+
index = index_for(key)
|
211
|
+
entry = (new_entries || @entries)[index]
|
212
|
+
if !entry
|
213
|
+
next
|
214
|
+
elsif entry[0].eql?(key)
|
215
|
+
new_entries ||= @entries.dup
|
216
|
+
child = (new_children || @children)[index]
|
217
|
+
if child
|
218
|
+
# Bring up the first entry from the child into entries
|
219
|
+
new_children ||= @children.dup
|
220
|
+
new_children[index] = child.delete_at do |entry|
|
221
|
+
new_entries[index] = entry
|
222
|
+
end
|
223
|
+
else
|
224
|
+
new_entries[index] = nil
|
225
|
+
end
|
226
|
+
new_size -= 1
|
227
|
+
else
|
228
|
+
child = (new_children || @children)[index]
|
229
|
+
if child
|
230
|
+
copy = child.find_and_delete(key)
|
231
|
+
unless copy.equal?(child)
|
232
|
+
new_children ||= @children.dup
|
233
|
+
new_children[index] = copy
|
234
|
+
new_size -= (child.size - copy_size(copy))
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
if new_entries || new_children
|
241
|
+
Trie.new(@significant_bits, new_size, new_entries || @entries, new_children || @children)
|
242
|
+
else
|
243
|
+
self
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
128
247
|
def include?(key, value)
|
129
248
|
entry = get(key)
|
130
249
|
entry && value.eql?(entry[1])
|
data/lib/hamster/vector.rb
CHANGED
@@ -1,31 +1,27 @@
|
|
1
|
-
require "forwardable"
|
2
1
|
require "hamster/immutable"
|
3
2
|
require "hamster/enumerable"
|
3
|
+
require "hamster/hash"
|
4
|
+
require "hamster/associable"
|
4
5
|
|
5
6
|
module Hamster
|
6
|
-
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
# A `Vector` is an ordered, integer-indexed collection of objects. Like `Array`,
|
11
|
-
# `Vector` indexing starts at 0. Also like `Array`, negative indexes count back
|
12
|
-
# from the end of the `Vector`.
|
7
|
+
# A `Vector` is an ordered, integer-indexed collection of objects. Like
|
8
|
+
# Ruby's `Array`, `Vector` indexing starts at zero and negative indexes count
|
9
|
+
# back from the end.
|
13
10
|
#
|
14
|
-
# `Vector`
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
11
|
+
# `Vector` has a similar interface to `Array`. The main difference is methods
|
12
|
+
# that would destructively update an `Array` (such as {#insert} or
|
13
|
+
# {#delete_at}) instead return new `Vectors` and leave the existing one
|
14
|
+
# unchanged.
|
18
15
|
#
|
19
|
-
#
|
16
|
+
# ### Creating New Vectors
|
20
17
|
#
|
21
|
-
# Hamster.vector('a', 'b', 'c')
|
22
18
|
# Hamster::Vector.new([:first, :second, :third])
|
23
19
|
# Hamster::Vector[1, 2, 3, 4, 5]
|
24
20
|
#
|
25
|
-
#
|
21
|
+
# ### Retrieving Items from Vectors
|
22
|
+
#
|
23
|
+
# vector = Hamster::Vector[1, 2, 3, 4, 5]
|
26
24
|
#
|
27
|
-
# require 'hamster/vector'
|
28
|
-
# vector = Hamster.vector(1, 2, 3, 4, 5)
|
29
25
|
# vector[0] # => 1
|
30
26
|
# vector[-1] # => 5
|
31
27
|
# vector[0,3] # => Hamster::Vector[1, 2, 3]
|
@@ -33,21 +29,17 @@ module Hamster
|
|
33
29
|
# vector.first # => 1
|
34
30
|
# vector.last # => 5
|
35
31
|
#
|
36
|
-
#
|
32
|
+
# ### Creating Modified Vectors
|
37
33
|
#
|
38
34
|
# vector.add(6) # => Hamster::Vector[1, 2, 3, 4, 5, 6]
|
39
35
|
# vector.insert(1, :a, :b) # => Hamster::Vector[1, :a, :b, 2, 3, 4, 5]
|
40
36
|
# vector.delete_at(2) # => Hamster::Vector[1, 2, 4, 5]
|
41
37
|
# vector + [6, 7] # => Hamster::Vector[1, 2, 3, 4, 5, 6, 7]
|
42
38
|
#
|
43
|
-
# Other `Array`-like methods like {#select}, {#map}, {#shuffle}, {#uniq}, {#reverse},
|
44
|
-
# {#rotate}, {#flatten}, {#sort}, {#sort_by}, {#take}, {#drop}, {#take_while},
|
45
|
-
# {#drop_while}, {#fill}, {#product}, and {#transpose} are also supported.
|
46
|
-
#
|
47
39
|
class Vector
|
48
|
-
extend Forwardable
|
49
40
|
include Immutable
|
50
41
|
include Enumerable
|
42
|
+
include Associable
|
51
43
|
|
52
44
|
# @private
|
53
45
|
BLOCK_SIZE = 32
|
@@ -59,7 +51,7 @@ module Hamster
|
|
59
51
|
# Return the number of items in this `Vector`
|
60
52
|
# @return [Integer]
|
61
53
|
attr_reader :size
|
62
|
-
|
54
|
+
alias :length :size
|
63
55
|
|
64
56
|
class << self
|
65
57
|
# Create a new `Vector` populated with the given items.
|
@@ -111,18 +103,22 @@ module Hamster
|
|
111
103
|
def empty?
|
112
104
|
@size == 0
|
113
105
|
end
|
114
|
-
def_delegator :self, :empty?, :null?
|
115
106
|
|
116
107
|
# Return the first item in the `Vector`. If the vector is empty, return `nil`.
|
117
108
|
#
|
109
|
+
# @example
|
110
|
+
# Hamster::Vector["A", "B", "C"].first # => "A"
|
111
|
+
#
|
118
112
|
# @return [Object]
|
119
113
|
def first
|
120
114
|
get(0)
|
121
115
|
end
|
122
|
-
def_delegator :self, :first, :head
|
123
116
|
|
124
117
|
# Return the last item in the `Vector`. If the vector is empty, return `nil`.
|
125
118
|
#
|
119
|
+
# @example
|
120
|
+
# Hamster::Vector["A", "B", "C"].last # => "C"
|
121
|
+
#
|
126
122
|
# @return [Object]
|
127
123
|
def last
|
128
124
|
get(-1)
|
@@ -130,33 +126,88 @@ module Hamster
|
|
130
126
|
|
131
127
|
# Return a new `Vector` with `item` added after the last occupied position.
|
132
128
|
#
|
129
|
+
# @example
|
130
|
+
# Hamster::Vector[1, 2].add(99) # => Hamster::Vector[1, 2, 99]
|
131
|
+
#
|
133
132
|
# @param item [Object] The object to insert at the end of the vector
|
134
133
|
# @return [Vector]
|
135
134
|
def add(item)
|
136
135
|
update_root(@size, item)
|
137
136
|
end
|
138
|
-
|
139
|
-
|
140
|
-
def_delegator :self, :add, :conjoin
|
141
|
-
def_delegator :self, :add, :push
|
137
|
+
alias :<< :add
|
138
|
+
alias :push :add
|
142
139
|
|
143
|
-
# Return a new `Vector` with
|
144
|
-
#
|
145
|
-
#
|
140
|
+
# Return a new `Vector` with a new value at the given `index`. If `index`
|
141
|
+
# is greater than the length of the vector, the returned vector will be
|
142
|
+
# padded with `nil`s to the correct size.
|
143
|
+
#
|
144
|
+
# @overload put(index, item)
|
145
|
+
# Return a new `Vector` with the item at `index` replaced by `item`.
|
146
146
|
#
|
147
|
-
#
|
148
|
-
#
|
147
|
+
# @param item [Object] The object to insert into that position
|
148
|
+
# @example
|
149
|
+
# Hamster::Vector[1, 2, 3, 4].put(2, 99)
|
150
|
+
# # => Hamster::Vector[1, 2, 99, 4]
|
151
|
+
# Hamster::Vector[1, 2, 3, 4].put(-1, 99)
|
152
|
+
# # => Hamster::Vector[1, 2, 3, 99]
|
153
|
+
# Hamster::Vector[].put(2, 99)
|
154
|
+
# # => Hamster::Vector[nil, nil, 99]
|
155
|
+
#
|
156
|
+
# @overload put(index)
|
157
|
+
# Return a new `Vector` with the item at `index` replaced by the return
|
158
|
+
# value of the block.
|
159
|
+
#
|
160
|
+
# @yield (existing) Once with the existing value at the given `index`.
|
161
|
+
# @example
|
162
|
+
# Hamster::Vector[1, 2, 3, 4].put(2) { |v| v * 10 }
|
163
|
+
# # => Hamster::Vector[1, 2, 30, 4]
|
164
|
+
#
|
165
|
+
# @param index [Integer] The index to update. May be negative.
|
149
166
|
# @return [Vector]
|
150
|
-
def
|
151
|
-
raise IndexError if
|
167
|
+
def put(index, item = yield(get(index)))
|
168
|
+
raise IndexError, "index #{index} outside of vector bounds" if index < -@size
|
152
169
|
index += @size if index < 0
|
153
|
-
|
154
|
-
|
170
|
+
if index > @size
|
171
|
+
suffix = Array.new(index - @size, nil)
|
172
|
+
suffix << item
|
173
|
+
replace_suffix(@size, suffix)
|
174
|
+
else
|
175
|
+
update_root(index, item)
|
176
|
+
end
|
155
177
|
end
|
178
|
+
alias :set :put
|
179
|
+
|
180
|
+
# Return a new `Vector` with a deeply nested value modified to the result
|
181
|
+
# of the given code block. When traversing the nested `Vector`s and
|
182
|
+
# `Hash`es, non-existing keys are created with empty `Hash` values.
|
183
|
+
#
|
184
|
+
# The code block receives the existing value of the deeply nested key (or
|
185
|
+
# `nil` if it doesn't exist). This is useful for "transforming" the value
|
186
|
+
# associated with a certain key.
|
187
|
+
#
|
188
|
+
# Note that the original `Vector` and sub-`Vector`s and sub-`Hash`es are
|
189
|
+
# left unmodified; new data structure copies are created along the path
|
190
|
+
# wherever needed.
|
191
|
+
#
|
192
|
+
# @example
|
193
|
+
# v = Hamster::Vector[123, 456, 789, Hamster::Hash["a" => Hamster::Vector[5, 6, 7]]]
|
194
|
+
# v.update_in(3, "a", 1) { |value| value + 9 }
|
195
|
+
# # => Hamster::Vector[123, 456, 789, Hamster::Hash["a" => Hamster::Vector[5, 15, 7]]]
|
196
|
+
#
|
197
|
+
# @param key_path [Object(s)] List of keys which form the path to the key to be modified
|
198
|
+
# @yield [value] The previously stored value
|
199
|
+
# @yieldreturn [Object] The new value to store
|
200
|
+
# @return [Vector]
|
156
201
|
|
157
202
|
# Retrieve the item at `index`. If there is none (either the provided index
|
158
203
|
# is too high or too low), return `nil`.
|
159
204
|
#
|
205
|
+
# @example
|
206
|
+
# v = Hamster::Vector["A", "B", "C", "D"]
|
207
|
+
# v.get(2) # => "C"
|
208
|
+
# v.get(-1) # => "D"
|
209
|
+
# v.get(4) # => nil
|
210
|
+
#
|
160
211
|
# @param index [Integer] The index to retrieve
|
161
212
|
# @return [Object]
|
162
213
|
def get(index)
|
@@ -165,26 +216,45 @@ module Hamster
|
|
165
216
|
return nil if index >= @size || index < 0
|
166
217
|
leaf_node_for(@root, @levels * BITS_PER_LEVEL, index)[index & INDEX_MASK]
|
167
218
|
end
|
168
|
-
|
219
|
+
alias :at :get
|
169
220
|
|
170
|
-
# Retrieve the value at `index
|
171
|
-
# or otherwise raise an `IndexError`.
|
221
|
+
# Retrieve the value at `index` with optional default.
|
172
222
|
#
|
173
223
|
# @overload fetch(index)
|
174
|
-
# Retrieve the value at the given index, or raise an `IndexError` if
|
175
|
-
#
|
224
|
+
# Retrieve the value at the given index, or raise an `IndexError` if not
|
225
|
+
# found.
|
226
|
+
#
|
176
227
|
# @param index [Integer] The index to look up
|
228
|
+
# @raise [IndexError] if index does not exist
|
229
|
+
# @example
|
230
|
+
# v = Hamster::Vector["A", "B", "C", "D"]
|
231
|
+
# v.fetch(2) # => "C"
|
232
|
+
# v.fetch(-1) # => "D"
|
233
|
+
# v.fetch(4) # => IndexError: index 4 outside of vector bounds
|
234
|
+
#
|
177
235
|
# @overload fetch(index) { |index| ... }
|
178
|
-
# Retrieve the value at the given index, or
|
179
|
-
#
|
180
|
-
#
|
181
|
-
# @
|
236
|
+
# Retrieve the value at the given index, or return the result of yielding
|
237
|
+
# the block if not found.
|
238
|
+
#
|
239
|
+
# @yield Once if the index is not found.
|
240
|
+
# @yieldparam [Integer] index The index which does not exist
|
241
|
+
# @yieldreturn [Object] Default value to return
|
182
242
|
# @param index [Integer] The index to look up
|
243
|
+
# @example
|
244
|
+
# v = Hamster::Vector["A", "B", "C", "D"]
|
245
|
+
# v.fetch(2) { |i| i * i } # => "C"
|
246
|
+
# v.fetch(4) { |i| i * i } # => 16
|
247
|
+
#
|
183
248
|
# @overload fetch(index, default)
|
184
|
-
# Retrieve the value at the given index, or
|
185
|
-
#
|
249
|
+
# Retrieve the value at the given index, or return the provided `default`
|
250
|
+
# value if not found.
|
251
|
+
#
|
186
252
|
# @param index [Integer] The index to look up
|
187
253
|
# @param default [Object] Object to return if the key is not found
|
254
|
+
# @example
|
255
|
+
# v = Hamster::Vector["A", "B", "C", "D"]
|
256
|
+
# v.fetch(2, "Z") # => "C"
|
257
|
+
# v.fetch(4, "Z") # => "Z"
|
188
258
|
#
|
189
259
|
# @return [Object]
|
190
260
|
def fetch(index, default = (missing_default = true))
|
@@ -199,22 +269,47 @@ module Hamster
|
|
199
269
|
end
|
200
270
|
end
|
201
271
|
|
202
|
-
#
|
203
|
-
#
|
272
|
+
# Return specific objects from the `Vector`. All overloads return `nil` if
|
273
|
+
# the starting index is out of range.
|
274
|
+
#
|
275
|
+
# @overload vector.slice(index)
|
276
|
+
# Returns a single object at the given `index`. If `index` is negative,
|
277
|
+
# count backwards from the end.
|
278
|
+
#
|
279
|
+
# @param index [Integer] The index to retrieve. May be negative.
|
280
|
+
# @return [Object]
|
281
|
+
# @example
|
282
|
+
# v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
|
283
|
+
# v[2] # => "C"
|
284
|
+
# v[-1] # => "F"
|
285
|
+
# v[6] # => nil
|
286
|
+
#
|
287
|
+
# @overload vector.slice(index, length)
|
288
|
+
# Return a subvector starting at `index` and continuing for `length`
|
289
|
+
# elements or until the end of the `Vector`, whichever occurs first.
|
204
290
|
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
# @param index [Integer] The index to retrieve.
|
208
|
-
# @overload vector[start, length]
|
209
|
-
# Return a subvector starting at index `start` and continuing for `length` elements.
|
210
|
-
# @param start [Integer] The index to start retrieving items from.
|
291
|
+
# @param start [Integer] The index to start retrieving items from. May be
|
292
|
+
# negative.
|
211
293
|
# @param length [Integer] The number of items to retrieve.
|
212
|
-
#
|
213
|
-
#
|
214
|
-
#
|
294
|
+
# @return [Vector]
|
295
|
+
# @example
|
296
|
+
# v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
|
297
|
+
# v[2, 3] # => Hamster::Vector["C", "D", "E"]
|
298
|
+
# v[-2, 3] # => Hamster::Vector["E", "F"]
|
299
|
+
# v[20, 1] # => nil
|
215
300
|
#
|
216
|
-
# @
|
217
|
-
|
301
|
+
# @overload vector.slice(index..end)
|
302
|
+
# Return a subvector starting at `index` and continuing to index
|
303
|
+
# `end` or the end of the `Vector`, whichever occurs first.
|
304
|
+
#
|
305
|
+
# @param range [Range] The range of indices to retrieve.
|
306
|
+
# @return [Vector]
|
307
|
+
# @example
|
308
|
+
# v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
|
309
|
+
# v[2..3] # => Hamster::Vector["C", "D"]
|
310
|
+
# v[-2..100] # => Hamster::Vector["E", "F"]
|
311
|
+
# v[20..21] # => nil
|
312
|
+
def slice(arg, length = (missing_length = true))
|
218
313
|
if missing_length
|
219
314
|
if arg.is_a?(Range)
|
220
315
|
from, to = arg.begin, arg.end
|
@@ -232,13 +327,22 @@ module Hamster
|
|
232
327
|
subsequence(arg, length)
|
233
328
|
end
|
234
329
|
end
|
235
|
-
|
330
|
+
alias :[] :slice
|
236
331
|
|
237
|
-
# Return a new `Vector` with the given values inserted before the element
|
332
|
+
# Return a new `Vector` with the given values inserted before the element
|
333
|
+
# at `index`. If `index` is greater than the current length, `nil` values
|
334
|
+
# are added to pad the `Vector` to the required size.
|
335
|
+
#
|
336
|
+
# @example
|
337
|
+
# Hamster::Vector["A", "B", "C", "D"].insert(2, "X", "Y", "Z")
|
338
|
+
# # => Hamster::Vector["A", "B", "X", "Y", "Z", "C", "D"]
|
339
|
+
# Hamster::Vector[].insert(2, "X", "Y", "Z")
|
340
|
+
# # => Hamster::Vector[nil, nil, "X", "Y", "Z"]
|
238
341
|
#
|
239
342
|
# @param index [Integer] The index where the new items should go
|
240
343
|
# @param items [Array] The items to add
|
241
344
|
# @return [Vector]
|
345
|
+
# @raise [IndexError] if index exceeds negative range.
|
242
346
|
def insert(index, *items)
|
243
347
|
raise IndexError if index < -@size
|
244
348
|
index += @size if index < 0
|
@@ -259,6 +363,10 @@ module Hamster
|
|
259
363
|
# Return a new `Vector` with the element at `index` removed. If the given `index`
|
260
364
|
# does not exist, return `self`.
|
261
365
|
#
|
366
|
+
# @example
|
367
|
+
# Hamster::Vector["A", "B", "C", "D"].delete_at(2)
|
368
|
+
# # => Hamster::Vector["A", "B", "D"]
|
369
|
+
#
|
262
370
|
# @param index [Integer] The index to remove
|
263
371
|
# @return [Vector]
|
264
372
|
def delete_at(index)
|
@@ -269,40 +377,70 @@ module Hamster
|
|
269
377
|
replace_suffix(index, suffix.tap { |a| a.shift })
|
270
378
|
end
|
271
379
|
|
272
|
-
# Return a new `Vector` with the last element removed.
|
380
|
+
# Return a new `Vector` with the last element removed. Return `self` if
|
381
|
+
# empty.
|
382
|
+
#
|
383
|
+
# @example
|
384
|
+
# Hamster::Vector["A", "B", "C"].pop # => Hamster::Vector["A", "B"]
|
385
|
+
#
|
273
386
|
# @return [Vector]
|
274
387
|
def pop
|
275
388
|
return self if @size == 0
|
276
389
|
replace_suffix(@size-1, [])
|
277
390
|
end
|
278
391
|
|
279
|
-
# Return a new `Vector` with `
|
280
|
-
# the other elements upwards.
|
281
|
-
#
|
392
|
+
# Return a new `Vector` with `object` inserted before the first element,
|
393
|
+
# moving the other elements upwards.
|
394
|
+
#
|
395
|
+
# @example
|
396
|
+
# Hamster::Vector["A", "B"].unshift("Z")
|
397
|
+
# # => Hamster::Vector["Z", "A", "B"]
|
398
|
+
#
|
399
|
+
# @param object [Object] The value to prepend
|
282
400
|
# @return [Vector]
|
283
|
-
def unshift(
|
284
|
-
insert(0,
|
401
|
+
def unshift(object)
|
402
|
+
insert(0, object)
|
285
403
|
end
|
286
404
|
|
287
|
-
# Return a new `Vector` with the first element removed. If empty,
|
405
|
+
# Return a new `Vector` with the first element removed. If empty, return
|
406
|
+
# `self`.
|
407
|
+
#
|
408
|
+
# @example
|
409
|
+
# Hamster::Vector["A", "B", "C"].shift # => Hamster::Vector["B", "C"]
|
410
|
+
#
|
288
411
|
# @return [Vector]
|
289
412
|
def shift
|
290
413
|
delete_at(0)
|
291
414
|
end
|
292
415
|
|
293
416
|
# Call the given block once for each item in the vector, passing each
|
294
|
-
# item from first to last successively to the block.
|
417
|
+
# item from first to last successively to the block. If no block is given,
|
418
|
+
# an `Enumerator` is returned instead.
|
295
419
|
#
|
296
|
-
# @
|
420
|
+
# @example
|
421
|
+
# Hamster::Vector["A", "B", "C"].each { |e| puts "Element: #{e}" }
|
422
|
+
#
|
423
|
+
# Element: A
|
424
|
+
# Element: B
|
425
|
+
# Element: C
|
426
|
+
# # => Hamster::Vector["A", "B", "C"]
|
427
|
+
#
|
428
|
+
# @return [self, Enumerator]
|
297
429
|
def each(&block)
|
298
430
|
return to_enum unless block_given?
|
299
431
|
traverse_depth_first(@root, @levels, &block)
|
300
432
|
self
|
301
433
|
end
|
302
434
|
|
303
|
-
# Call the given block once for each item in the vector,
|
304
|
-
#
|
305
|
-
#
|
435
|
+
# Call the given block once for each item in the vector, from last to
|
436
|
+
# first.
|
437
|
+
#
|
438
|
+
# @example
|
439
|
+
# Hamster::Vector["A", "B", "C"].reverse_each { |e| puts "Element: #{e}" }
|
440
|
+
#
|
441
|
+
# Element: C
|
442
|
+
# Element: B
|
443
|
+
# Element: A
|
306
444
|
#
|
307
445
|
# @return [self]
|
308
446
|
def reverse_each(&block)
|
@@ -314,34 +452,65 @@ module Hamster
|
|
314
452
|
# Return a new `Vector` containing all elements for which the given block returns
|
315
453
|
# true.
|
316
454
|
#
|
455
|
+
# @example
|
456
|
+
# Hamster::Vector["Bird", "Cow", "Elephant"].select { |e| e.size >= 4 }
|
457
|
+
# # => Hamster::Vector["Bird", "Elephant"]
|
458
|
+
#
|
317
459
|
# @return [Vector]
|
318
|
-
|
319
|
-
|
460
|
+
# @yield [element] Once for each element.
|
461
|
+
def select
|
462
|
+
return enum_for(:select) unless block_given?
|
320
463
|
reduce(self.class.empty) { |vector, item| yield(item) ? vector.add(item) : vector }
|
321
464
|
end
|
465
|
+
alias :find_all :select
|
466
|
+
alias :keep_if :select
|
322
467
|
|
323
468
|
# Return a new `Vector` with all items which are equal to `obj` removed.
|
324
469
|
# `#==` is used for checking equality.
|
325
470
|
#
|
471
|
+
# @example
|
472
|
+
# Hamster::Vector["C", "B", "A", "B"].delete("B") # => Hamster::Vector["C", "A"]
|
473
|
+
#
|
326
474
|
# @param obj [Object] The object to remove (every occurrence)
|
327
475
|
# @return [Vector]
|
328
476
|
def delete(obj)
|
329
|
-
|
477
|
+
select { |item| item != obj }
|
330
478
|
end
|
331
479
|
|
332
480
|
# Invoke the given block once for each item in the vector, and return a new
|
333
|
-
# `Vector` containing the values returned by the block.
|
481
|
+
# `Vector` containing the values returned by the block. If no block is
|
482
|
+
# provided, return an enumerator.
|
334
483
|
#
|
335
|
-
# @
|
484
|
+
# @example
|
485
|
+
# Hamster::Vector[3, 2, 1].map { |e| e * e } # => Hamster::Vector[9, 4, 1]
|
486
|
+
#
|
487
|
+
# @return [Vector, Enumerator]
|
336
488
|
def map
|
337
489
|
return enum_for(:map) if not block_given?
|
338
490
|
return self if empty?
|
339
491
|
self.class.new(super)
|
340
492
|
end
|
341
|
-
|
493
|
+
alias :collect :map
|
494
|
+
|
495
|
+
# Return a new `Vector` with the concatenated results of running the block once
|
496
|
+
# for every element in this `Vector`.
|
497
|
+
#
|
498
|
+
# @example
|
499
|
+
# Hamster::Vector[1, 2, 3].flat_map { |x| [x, -x] }
|
500
|
+
# # => Hamster::Vector[1, -1, 2, -2, 3, -3]
|
501
|
+
#
|
502
|
+
# @return [Vector]
|
503
|
+
def flat_map
|
504
|
+
return enum_for(:flat_map) if not block_given?
|
505
|
+
return self if empty?
|
506
|
+
self.class.new(super)
|
507
|
+
end
|
342
508
|
|
343
509
|
# Return a new `Vector` with the same elements as this one, but randomly permuted.
|
344
510
|
#
|
511
|
+
# @example
|
512
|
+
# Hamster::Vector[1, 2, 3, 4].shuffle # => Hamster::Vector[4, 1, 3, 2]
|
513
|
+
#
|
345
514
|
# @return [Vector]
|
346
515
|
def shuffle
|
347
516
|
self.class.new(((array = to_a).frozen? ? array.shuffle : array.shuffle!).freeze)
|
@@ -350,13 +519,35 @@ module Hamster
|
|
350
519
|
# Return a new `Vector` with no duplicate elements, as determined by `#hash` and
|
351
520
|
# `#eql?`. For each group of equivalent elements, only the first will be retained.
|
352
521
|
#
|
522
|
+
# @example
|
523
|
+
# Hamster::Vector["A", "B", "C", "B"].uniq # => Hamster::Vector["A", "B", "C"]
|
524
|
+
# Hamster::Vector["a", "A", "b"].uniq(&:upcase) # => Hamster::Vector["a", "b"]
|
525
|
+
#
|
353
526
|
# @return [Vector]
|
354
|
-
def uniq
|
355
|
-
|
527
|
+
def uniq(&block)
|
528
|
+
array = self.to_a
|
529
|
+
if block_given?
|
530
|
+
if array.frozen?
|
531
|
+
self.class.new(array.uniq(&block).freeze)
|
532
|
+
elsif array.uniq!(&block) # returns nil if no changes were made
|
533
|
+
self.class.new(array.freeze)
|
534
|
+
else
|
535
|
+
self
|
536
|
+
end
|
537
|
+
elsif array.frozen?
|
538
|
+
self.class.new(array.uniq.freeze)
|
539
|
+
elsif array.uniq! # returns nil if no changes were made
|
540
|
+
self.class.new(array.freeze)
|
541
|
+
else
|
542
|
+
self
|
543
|
+
end
|
356
544
|
end
|
357
545
|
|
358
546
|
# Return a new `Vector` with the same elements as this one, but in reverse order.
|
359
547
|
#
|
548
|
+
# @example
|
549
|
+
# Hamster::Vector["A", "B", "C"].reverse # => Hamster::Vector["C", "B", "A"]
|
550
|
+
#
|
360
551
|
# @return [Vector]
|
361
552
|
def reverse
|
362
553
|
self.class.new(((array = to_a).frozen? ? array.reverse : array.reverse!).freeze)
|
@@ -368,6 +559,11 @@ module Hamster
|
|
368
559
|
# will be moved to the end. If `count` is negative, the elements will be shifted
|
369
560
|
# right, and those shifted past the last position will be moved to the beginning.
|
370
561
|
#
|
562
|
+
# @example
|
563
|
+
# v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
|
564
|
+
# v.rotate(2) # => Hamster::Vector["C", "D", "E", "F", "A", "B"]
|
565
|
+
# v.rotate(-1) # => Hamster::Vector["F", "A", "B", "C", "D", "E"]
|
566
|
+
#
|
371
567
|
# @param count [Integer] The number of positions to shift items by
|
372
568
|
# @return [Vector]
|
373
569
|
def rotate(count = 1)
|
@@ -376,22 +572,40 @@ module Hamster
|
|
376
572
|
end
|
377
573
|
|
378
574
|
# Return a new `Vector` with all nested vectors and arrays recursively "flattened
|
379
|
-
# out"
|
575
|
+
# out". That is, their elements inserted into the new `Vector` in the place where
|
380
576
|
# the nested array/vector originally was. If an optional `level` argument is
|
381
577
|
# provided, the flattening will only be done recursively that number of times.
|
382
578
|
# A `level` of 0 means not to flatten at all, 1 means to only flatten nested
|
383
579
|
# arrays/vectors which are directly contained within this `Vector`.
|
384
580
|
#
|
581
|
+
# @example
|
582
|
+
# v = Hamster::Vector["A", Hamster::Vector["B", "C", Hamster::Vector["D"]]]
|
583
|
+
# v.flatten(1)
|
584
|
+
# # => Hamster::Vector["A", "B", "C", Hamster::Vector["D"]]
|
585
|
+
# v.flatten
|
586
|
+
# # => Hamster::Vector["A", "B", "C", "D"]
|
587
|
+
#
|
385
588
|
# @param level [Integer] The depth to which flattening should be applied
|
386
589
|
# @return [Vector]
|
387
|
-
def flatten(level =
|
590
|
+
def flatten(level = -1)
|
388
591
|
return self if level == 0
|
389
|
-
|
592
|
+
array = self.to_a
|
593
|
+
if array.frozen?
|
594
|
+
self.class.new(array.flatten(level).freeze)
|
595
|
+
elsif array.flatten!(level) # returns nil if no changes were made
|
596
|
+
self.class.new(array.freeze)
|
597
|
+
else
|
598
|
+
self
|
599
|
+
end
|
390
600
|
end
|
391
601
|
|
392
602
|
# Return a new `Vector` built by concatenating this one with `other`. `other`
|
393
603
|
# can be any object which is convertible to an `Array` using `#to_a`.
|
394
604
|
#
|
605
|
+
# @example
|
606
|
+
# Hamster::Vector["A", "B", "C"] + ["D", "E"]
|
607
|
+
# # => Hamster::Vector["A", "B", "C", "D", "E"]
|
608
|
+
#
|
395
609
|
# @param other [Enumerable] The collection to concatenate onto this vector
|
396
610
|
# @return [Vector]
|
397
611
|
def +(other)
|
@@ -399,17 +613,33 @@ module Hamster
|
|
399
613
|
other = other.dup if other.frozen?
|
400
614
|
replace_suffix(@size, other)
|
401
615
|
end
|
402
|
-
|
616
|
+
alias :concat :+
|
403
617
|
|
404
|
-
#
|
405
|
-
#
|
406
|
-
# will be gathered
|
618
|
+
# Combine two vectors by "zipping" them together. `others` should be arrays
|
619
|
+
# and/or vectors. The corresponding elements from this `Vector` and each of
|
620
|
+
# `others` (that is, the elements with the same indices) will be gathered
|
621
|
+
# into arrays.
|
622
|
+
#
|
623
|
+
# If `others` contains fewer elements than this vector, `nil` will be used
|
624
|
+
# for padding.
|
407
625
|
#
|
408
|
-
#
|
409
|
-
#
|
626
|
+
# @overload zip(*others)
|
627
|
+
# Return a new vector containing the new arrays.
|
628
|
+
#
|
629
|
+
# @return [Vector]
|
630
|
+
#
|
631
|
+
# @overload zip(*others)
|
632
|
+
# @yield [pair] once for each array
|
633
|
+
# @return [nil]
|
634
|
+
#
|
635
|
+
# @example
|
636
|
+
# v1 = Hamster::Vector["A", "B", "C"]
|
637
|
+
# v2 = Hamster::Vector[1, 2]
|
638
|
+
# v1.zip(v2)
|
639
|
+
# # => Hamster::Vector[["A", 1], ["B", 2], ["C", nil]]
|
410
640
|
#
|
411
641
|
# @param others [Array] The arrays/vectors to zip together with this one
|
412
|
-
# @return [Vector
|
642
|
+
# @return [Vector]
|
413
643
|
def zip(*others)
|
414
644
|
if block_given?
|
415
645
|
super
|
@@ -418,20 +648,41 @@ module Hamster
|
|
418
648
|
end
|
419
649
|
end
|
420
650
|
|
421
|
-
# Return a new `Vector` with the same items, but sorted.
|
422
|
-
#
|
423
|
-
#
|
424
|
-
#
|
425
|
-
#
|
651
|
+
# Return a new `Vector` with the same items, but sorted.
|
652
|
+
#
|
653
|
+
# @overload sort
|
654
|
+
# Compare elements with their natural sort key (`#<=>`).
|
655
|
+
#
|
656
|
+
# @example
|
657
|
+
# Hamster::Vector["Elephant", "Dog", "Lion"].sort
|
658
|
+
# # => Hamster::Vector["Dog", "Elephant", "Lion"]
|
659
|
+
#
|
660
|
+
# @overload sort
|
661
|
+
# Uses the block as a comparator to determine sorted order.
|
662
|
+
#
|
663
|
+
# @yield [a, b] Any number of times with different pairs of elements.
|
664
|
+
# @yieldreturn [Integer] Negative if the first element should be sorted
|
665
|
+
# lower, positive if the latter element, or 0 if
|
666
|
+
# equal.
|
667
|
+
# @example
|
668
|
+
# Hamster::Vector["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
|
669
|
+
# # => Hamster::Vector["Dog", "Lion", "Elephant"]
|
426
670
|
#
|
427
671
|
# @return [Vector]
|
428
672
|
def sort
|
429
673
|
self.class.new(super)
|
430
674
|
end
|
431
675
|
|
432
|
-
# Return a new `Vector` with the same items, but sorted. The sort order
|
433
|
-
# determined by mapping the items through the given block to obtain sort
|
434
|
-
# and then sorting the keys according to their natural sort order
|
676
|
+
# Return a new `Vector` with the same items, but sorted. The sort order is
|
677
|
+
# determined by mapping the items through the given block to obtain sort
|
678
|
+
# keys, and then sorting the keys according to their natural sort order
|
679
|
+
# (`#<=>`).
|
680
|
+
#
|
681
|
+
# @yield [element] Once for each element.
|
682
|
+
# @yieldreturn a sort key object for the yielded element.
|
683
|
+
# @example
|
684
|
+
# Hamster::Vector["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
|
685
|
+
# # => Hamster::Vector["Dog", "Lion", "Elephant"]
|
435
686
|
#
|
436
687
|
# @return [Vector]
|
437
688
|
def sort_by
|
@@ -439,16 +690,31 @@ module Hamster
|
|
439
690
|
end
|
440
691
|
|
441
692
|
# Drop the first `n` elements and return the rest in a new `Vector`.
|
693
|
+
#
|
694
|
+
# @example
|
695
|
+
# Hamster::Vector["A", "B", "C", "D", "E", "F"].drop(2)
|
696
|
+
# # => Hamster::Vector["C", "D", "E", "F"]
|
697
|
+
#
|
442
698
|
# @param n [Integer] The number of elements to remove
|
443
699
|
# @return [Vector]
|
700
|
+
# @raise ArgumentError if `n` is negative.
|
444
701
|
def drop(n)
|
445
|
-
self
|
702
|
+
return self if n == 0
|
703
|
+
return self.class.empty if n >= @size
|
704
|
+
raise ArgumentError, "attempt to drop negative size" if n < 0
|
705
|
+
self.class.new(flatten_suffix(@root, @levels * BITS_PER_LEVEL, n, []))
|
446
706
|
end
|
447
707
|
|
448
708
|
# Return only the first `n` elements in a new `Vector`.
|
709
|
+
#
|
710
|
+
# @example
|
711
|
+
# Hamster::Vector["A", "B", "C", "D", "E", "F"].take(4)
|
712
|
+
# # => Hamster::Vector["A", "B", "C", "D"]
|
713
|
+
#
|
449
714
|
# @param n [Integer] The number of elements to retain
|
450
715
|
# @return [Vector]
|
451
716
|
def take(n)
|
717
|
+
return self if n >= @size
|
452
718
|
self.class.new(super)
|
453
719
|
end
|
454
720
|
|
@@ -456,6 +722,10 @@ module Hamster
|
|
456
722
|
# block returns `nil` or `false`. Gather the remaining elements into a new
|
457
723
|
# `Vector`. If no block is given, an `Enumerator` is returned instead.
|
458
724
|
#
|
725
|
+
# @example
|
726
|
+
# Hamster::Vector[1, 3, 5, 7, 6, 4, 2].drop_while { |e| e < 5 }
|
727
|
+
# # => Hamster::Vector[5, 7, 6, 4, 2]
|
728
|
+
#
|
459
729
|
# @return [Vector, Enumerator]
|
460
730
|
def drop_while
|
461
731
|
return enum_for(:drop_while) if not block_given?
|
@@ -466,6 +736,10 @@ module Hamster
|
|
466
736
|
# block returns `nil` or `false`, and return them in a new `Vector`. If no block
|
467
737
|
# is given, an `Enumerator` is returned instead.
|
468
738
|
#
|
739
|
+
# @example
|
740
|
+
# Hamster::Vector[1, 3, 5, 7, 6, 4, 2].take_while { |e| e < 5 }
|
741
|
+
# # => Hamster::Vector[1, 3]
|
742
|
+
#
|
469
743
|
# @return [Vector, Enumerator]
|
470
744
|
def take_while
|
471
745
|
return enum_for(:take_while) if not block_given?
|
@@ -475,6 +749,10 @@ module Hamster
|
|
475
749
|
# Repetition. Return a new `Vector` built by concatenating `times` copies
|
476
750
|
# of this one together.
|
477
751
|
#
|
752
|
+
# @example
|
753
|
+
# Hamster::Vector["A", "B"] * 3
|
754
|
+
# # => Hamster::Vector["A", "B", "A", "B", "A", "B"]
|
755
|
+
#
|
478
756
|
# @param times [Integer] The number of times to repeat the elements in this vector
|
479
757
|
# @return [Vector]
|
480
758
|
def *(times)
|
@@ -486,28 +764,53 @@ module Hamster
|
|
486
764
|
|
487
765
|
# Replace a range of indexes with the given object.
|
488
766
|
#
|
489
|
-
# @overload fill(
|
490
|
-
# Return a new `Vector` of the same size, with every index set to
|
491
|
-
#
|
492
|
-
#
|
493
|
-
#
|
494
|
-
#
|
495
|
-
#
|
496
|
-
#
|
767
|
+
# @overload fill(object)
|
768
|
+
# Return a new `Vector` of the same size, with every index set to
|
769
|
+
# `object`.
|
770
|
+
#
|
771
|
+
# @param [Object] object Fill value.
|
772
|
+
# @example
|
773
|
+
# Hamster::Vector["A", "B", "C", "D", "E", "F"].fill("Z")
|
774
|
+
# # => Hamster::Vector["Z", "Z", "Z", "Z", "Z", "Z"]
|
775
|
+
#
|
776
|
+
# @overload fill(object, index)
|
777
|
+
# Return a new `Vector` with all indexes from `index` to the end of the
|
778
|
+
# vector set to `object`.
|
779
|
+
#
|
780
|
+
# @param [Object] object Fill value.
|
781
|
+
# @param [Integer] index Starting index. May be negative.
|
782
|
+
# @example
|
783
|
+
# Hamster::Vector["A", "B", "C", "D", "E", "F"].fill("Z", 3)
|
784
|
+
# # => Hamster::Vector["A", "B", "C", "Z", "Z", "Z"]
|
785
|
+
#
|
786
|
+
# @overload fill(object, index, length)
|
787
|
+
# Return a new `Vector` with `length` indexes, beginning from `index`,
|
788
|
+
# set to `object`. Expands the `Vector` if `length` would extend beyond
|
789
|
+
# the current length.
|
790
|
+
#
|
791
|
+
# @param [Object] object Fill value.
|
792
|
+
# @param [Integer] index Starting index. May be negative.
|
793
|
+
# @param [Integer] length
|
794
|
+
# @example
|
795
|
+
# Hamster::Vector["A", "B", "C", "D", "E", "F"].fill("Z", 3, 2)
|
796
|
+
# # => Hamster::Vector["A", "B", "C", "Z", "Z", "F"]
|
797
|
+
# Hamster::Vector["A", "B"].fill("Z", 1, 5)
|
798
|
+
# # => Hamster::Vector["A", "Z", "Z", "Z", "Z", "Z"]
|
497
799
|
#
|
498
800
|
# @return [Vector]
|
499
|
-
|
801
|
+
# @raise [IndexError] if index is out of negative range.
|
802
|
+
def fill(object, index = 0, length = nil)
|
500
803
|
raise IndexError if index < -@size
|
501
804
|
index += @size if index < 0
|
502
805
|
length ||= @size - index # to the end of the array, if no length given
|
503
806
|
|
504
807
|
if index < @size
|
505
808
|
suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
|
506
|
-
suffix.fill(
|
809
|
+
suffix.fill(object, 0, length)
|
507
810
|
elsif index == @size
|
508
|
-
suffix = Array.new(length,
|
811
|
+
suffix = Array.new(length, object)
|
509
812
|
else
|
510
|
-
suffix = Array.new(index - @size, nil).concat(Array.new(length,
|
813
|
+
suffix = Array.new(index - @size, nil).concat(Array.new(length, object))
|
511
814
|
index = @size
|
512
815
|
end
|
513
816
|
|
@@ -516,10 +819,20 @@ module Hamster
|
|
516
819
|
|
517
820
|
# When invoked with a block, yields all combinations of length `n` of items
|
518
821
|
# from the `Vector`, and then returns `self`. There is no guarantee about
|
519
|
-
# which order the combinations will be yielded
|
822
|
+
# which order the combinations will be yielded.
|
520
823
|
#
|
521
824
|
# If no block is given, an `Enumerator` is returned instead.
|
522
825
|
#
|
826
|
+
# @example
|
827
|
+
# v = Hamster::Vector[5, 6, 7, 8]
|
828
|
+
# v.combination(3) { |c| puts "Combination: #{c}" }
|
829
|
+
#
|
830
|
+
# Combination: [5, 6, 7]
|
831
|
+
# Combination: [5, 6, 8]
|
832
|
+
# Combination: [5, 7, 8]
|
833
|
+
# Combination: [6, 7, 8]
|
834
|
+
# #=> Hamster::Vector[5, 6, 7, 8]
|
835
|
+
#
|
523
836
|
# @return [self, Enumerator]
|
524
837
|
def combination(n)
|
525
838
|
return enum_for(:combination, n) if not block_given?
|
@@ -557,6 +870,22 @@ module Hamster
|
|
557
870
|
#
|
558
871
|
# If no block is given, an `Enumerator` is returned instead.
|
559
872
|
#
|
873
|
+
# @example
|
874
|
+
# v = Hamster::Vector[5, 6, 7, 8]
|
875
|
+
# v.repeated_combination(2) { |c| puts "Combination: #{c}" }
|
876
|
+
#
|
877
|
+
# Combination: [5, 5]
|
878
|
+
# Combination: [5, 6]
|
879
|
+
# Combination: [5, 7]
|
880
|
+
# Combination: [5, 8]
|
881
|
+
# Combination: [6, 6]
|
882
|
+
# Combination: [6, 7]
|
883
|
+
# Combination: [6, 8]
|
884
|
+
# Combination: [7, 7]
|
885
|
+
# Combination: [7, 8]
|
886
|
+
# Combination: [8, 8]
|
887
|
+
# # => Hamster::Vector[5, 6, 7, 8]
|
888
|
+
#
|
560
889
|
# @return [self, Enumerator]
|
561
890
|
def repeated_combination(n)
|
562
891
|
return enum_for(:repeated_combination, n) if not block_given?
|
@@ -595,6 +924,18 @@ module Hamster
|
|
595
924
|
#
|
596
925
|
# If no block is given, an `Enumerator` is returned instead.
|
597
926
|
#
|
927
|
+
# @example
|
928
|
+
# v = Hamster::Vector[5, 6, 7]
|
929
|
+
# v.permutation(2) { |p| puts "Permutation: #{p}" }
|
930
|
+
#
|
931
|
+
# Permutation: [5, 6]
|
932
|
+
# Permutation: [5, 7]
|
933
|
+
# Permutation: [6, 5]
|
934
|
+
# Permutation: [6, 7]
|
935
|
+
# Permutation: [7, 5]
|
936
|
+
# Permutation: [7, 6]
|
937
|
+
# # => Hamster::Vector[5, 6, 7]
|
938
|
+
#
|
598
939
|
# @return [self, Enumerator]
|
599
940
|
def permutation(n = @size)
|
600
941
|
return enum_for(:permutation, n) if not block_given?
|
@@ -635,6 +976,21 @@ module Hamster
|
|
635
976
|
#
|
636
977
|
# If no block is given, an `Enumerator` is returned instead.
|
637
978
|
#
|
979
|
+
# @example
|
980
|
+
# v = Hamster::Vector[5, 6, 7]
|
981
|
+
# v.repeated_permutation(2) { |p| puts "Permutation: #{p}" }
|
982
|
+
#
|
983
|
+
# Permutation: [5, 5]
|
984
|
+
# Permutation: [5, 6]
|
985
|
+
# Permutation: [5, 7]
|
986
|
+
# Permutation: [6, 5]
|
987
|
+
# Permutation: [6, 6]
|
988
|
+
# Permutation: [6, 7]
|
989
|
+
# Permutation: [7, 5]
|
990
|
+
# Permutation: [7, 6]
|
991
|
+
# Permutation: [7, 7]
|
992
|
+
# # => Hamster::Vector[5, 6, 7]
|
993
|
+
#
|
638
994
|
# @return [self, Enumerator]
|
639
995
|
def repeated_permutation(n = @size)
|
640
996
|
return enum_for(:repeated_permutation, n) if not block_given?
|
@@ -661,17 +1017,23 @@ module Hamster
|
|
661
1017
|
self
|
662
1018
|
end
|
663
1019
|
|
664
|
-
#
|
665
|
-
# this vector's elements and those of each argument; with no arguments, return the
|
666
|
-
# result of multiplying all this vector's items together.
|
1020
|
+
# Cartesian product or multiplication.
|
667
1021
|
#
|
668
1022
|
# @overload product(*vectors)
|
669
1023
|
# Return a `Vector` of all combinations of elements from this `Vector` and each
|
670
1024
|
# of the given vectors or arrays. The length of the returned `Vector` is the product
|
671
1025
|
# of `self.size` and the size of each argument vector or array.
|
1026
|
+
# @example
|
1027
|
+
# v1 = Hamster::Vector[1, 2, 3]
|
1028
|
+
# v2 = Hamster::Vector["A", "B"]
|
1029
|
+
# v1.product(v2)
|
1030
|
+
# # => [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"], [3, "B"]]
|
672
1031
|
# @overload product
|
673
1032
|
# Return the result of multiplying all the items in this `Vector` together.
|
674
1033
|
#
|
1034
|
+
# @example
|
1035
|
+
# Hamster::Vector[1, 2, 3, 4, 5].product # => 120
|
1036
|
+
#
|
675
1037
|
# @return [Vector]
|
676
1038
|
def product(*vectors)
|
677
1039
|
# if no vectors passed, return "product" as in result of multiplying all items
|
@@ -726,7 +1088,13 @@ module Hamster
|
|
726
1088
|
# calling {#zip} on the first nested vector/array with the others supplied as
|
727
1089
|
# arguments.
|
728
1090
|
#
|
1091
|
+
# @example
|
1092
|
+
# Hamster::Vector[["A", 10], ["B", 20], ["C", 30]].transpose
|
1093
|
+
# # => Hamster::Vector[Hamster::Vector["A", "B", "C"], Hamster::Vector[10, 20, 30]]
|
1094
|
+
#
|
729
1095
|
# @return [Vector]
|
1096
|
+
# @raise [IndexError] if elements are not of the same size.
|
1097
|
+
# @raise [TypeError] if an element can not be implicitly converted to an array (using `#to_ary`)
|
730
1098
|
def transpose
|
731
1099
|
return self.class.empty if empty?
|
732
1100
|
result = Array.new(first.size) { [] }
|
@@ -746,12 +1114,28 @@ module Hamster
|
|
746
1114
|
self.class.new(result)
|
747
1115
|
end
|
748
1116
|
|
749
|
-
#
|
750
|
-
#
|
751
|
-
# See `Array#bsearch` for details
|
1117
|
+
# Finds a value from this `Vector` which meets the condition defined by the
|
1118
|
+
# provided block, using a binary search. The vector must already be sorted
|
1119
|
+
# with respect to the block. See Ruby's `Array#bsearch` for details,
|
1120
|
+
# behaviour is equivalent.
|
752
1121
|
#
|
753
|
-
# @
|
1122
|
+
# @example
|
1123
|
+
# v = Hamster::Vector[1, 3, 5, 7, 9, 11, 13]
|
1124
|
+
# # Block returns true/false for exact element match:
|
1125
|
+
# v.bsearch { |e| e > 4 } # => 5
|
1126
|
+
# # Block returns number to match an element in 4 <= e <= 7:
|
1127
|
+
# v.bsearch { |e| 1 - e / 4 } # => 7
|
1128
|
+
#
|
1129
|
+
# @yield Once for at most `log n` elements, where `n` is the size of the
|
1130
|
+
# vector. The exact elements and ordering are undefined.
|
1131
|
+
# @yieldreturn [Boolean] `true` if this element matches the criteria, `false` otherwise.
|
1132
|
+
# @yieldreturn [Integer] See `Array#bsearch` for details.
|
1133
|
+
# @yieldparam [Object] element element to be evaluated
|
1134
|
+
# @return [Object] The matched element, or `nil` if none found.
|
1135
|
+
# @raise TypeError if the block returns a non-numeric, non-boolean, non-nil
|
1136
|
+
# value.
|
754
1137
|
def bsearch
|
1138
|
+
return enum_for(:bsearch) if not block_given?
|
755
1139
|
low, high, result = 0, @size, nil
|
756
1140
|
while low < high
|
757
1141
|
mid = (low + ((high - low) >> 1))
|
@@ -787,6 +1171,9 @@ module Hamster
|
|
787
1171
|
|
788
1172
|
# Return a randomly chosen item from this `Vector`. If the vector is empty, return `nil`.
|
789
1173
|
#
|
1174
|
+
# @example
|
1175
|
+
# Hamster::Vector[1, 2, 3, 4, 5].sample # => 2
|
1176
|
+
#
|
790
1177
|
# @return [Object]
|
791
1178
|
def sample
|
792
1179
|
get(rand(@size))
|
@@ -796,23 +1183,36 @@ module Hamster
|
|
796
1183
|
# order specified by `indices`. If any of the `indices` do not exist, `nil`s will
|
797
1184
|
# appear in their places.
|
798
1185
|
#
|
1186
|
+
# @example
|
1187
|
+
# v = Hamster::Vector["A", "B", "C", "D", "E", "F"]
|
1188
|
+
# v.values_at(2, 4, 5) # => Hamster::Vector["C", "E", "F"]
|
1189
|
+
#
|
799
1190
|
# @param indices [Array] The indices to retrieve and gather into a new `Vector`
|
800
1191
|
# @return [Vector]
|
801
1192
|
def values_at(*indices)
|
802
1193
|
self.class.new(indices.map { |i| get(i) }.freeze)
|
803
1194
|
end
|
804
1195
|
|
805
|
-
#
|
806
|
-
#
|
1196
|
+
# Find the index of an element, starting from the end of the vector.
|
1197
|
+
# Returns `nil` if no element is found.
|
807
1198
|
#
|
808
1199
|
# @overload rindex(obj)
|
809
|
-
# Return the index of the last element
|
810
|
-
#
|
811
|
-
#
|
812
|
-
#
|
813
|
-
#
|
1200
|
+
# Return the index of the last element which is `#==` to `obj`.
|
1201
|
+
#
|
1202
|
+
# @example
|
1203
|
+
# v = Hamster::Vector[7, 8, 9, 7, 8, 9]
|
1204
|
+
# v.rindex(8) # => 4
|
1205
|
+
#
|
1206
|
+
# @overload rindex
|
1207
|
+
# Return the index of the last element for which the block returns true.
|
814
1208
|
#
|
815
|
-
#
|
1209
|
+
# @yield [element] Once for each element, last to first, until the block
|
1210
|
+
# returns true.
|
1211
|
+
# @example
|
1212
|
+
# v = Hamster::Vector[7, 8, 9, 7, 8, 9]
|
1213
|
+
# v.rindex { |e| e.even? } # => 4
|
1214
|
+
#
|
1215
|
+
# @return [Integer]
|
816
1216
|
def rindex(obj = (missing_arg = true))
|
817
1217
|
i = @size - 1
|
818
1218
|
if missing_arg
|
@@ -831,22 +1231,40 @@ module Hamster
|
|
831
1231
|
# Assumes all elements are nested, indexable collections, and searches through them,
|
832
1232
|
# comparing `obj` with the first element of each nested collection. Return the
|
833
1233
|
# first nested collection which matches, or `nil` if none is found.
|
1234
|
+
# Behaviour is undefined when elements do not meet assumptions (i.e. are
|
1235
|
+
# not indexable collections).
|
1236
|
+
#
|
1237
|
+
# @example
|
1238
|
+
# v = Hamster::Vector[["A", 10], ["B", 20], ["C", 30]]
|
1239
|
+
# v.assoc("B") # => ["B", 20]
|
834
1240
|
#
|
835
1241
|
# @param obj [Object] The object to search for
|
836
1242
|
# @return [Object]
|
837
1243
|
def assoc(obj)
|
838
|
-
each
|
1244
|
+
each do |array|
|
1245
|
+
next if !array.respond_to?(:[])
|
1246
|
+
return array if obj == array[0]
|
1247
|
+
end
|
839
1248
|
nil
|
840
1249
|
end
|
841
1250
|
|
842
1251
|
# Assumes all elements are nested, indexable collections, and searches through them,
|
843
|
-
# comparing `obj` with the second element of each nested collection. Return
|
844
|
-
# first nested collection which matches, or `nil` if none is found.
|
1252
|
+
# comparing `obj` with the second element of each nested collection. Return
|
1253
|
+
# the first nested collection which matches, or `nil` if none is found.
|
1254
|
+
# Behaviour is undefined when elements do not meet assumptions (i.e. are
|
1255
|
+
# not indexable collections).
|
1256
|
+
#
|
1257
|
+
# @example
|
1258
|
+
# v = Hamster::Vector[["A", 10], ["B", 20], ["C", 30]]
|
1259
|
+
# v.rassoc(20) # => ["B", 20]
|
845
1260
|
#
|
846
1261
|
# @param obj [Object] The object to search for
|
847
1262
|
# @return [Object]
|
848
1263
|
def rassoc(obj)
|
849
|
-
each
|
1264
|
+
each do |array|
|
1265
|
+
next if !array.respond_to?(:[])
|
1266
|
+
return array if obj == array[1]
|
1267
|
+
end
|
850
1268
|
nil
|
851
1269
|
end
|
852
1270
|
|
@@ -856,11 +1274,14 @@ module Hamster
|
|
856
1274
|
# @return [Array]
|
857
1275
|
def to_a
|
858
1276
|
if @levels == 0
|
1277
|
+
# When initializing a Vector with 32 or less items, we always make
|
1278
|
+
# sure @root is frozen, so we can return it directly here
|
859
1279
|
@root
|
860
1280
|
else
|
861
1281
|
flatten_node(@root, @levels * BITS_PER_LEVEL, [])
|
862
1282
|
end
|
863
1283
|
end
|
1284
|
+
alias :to_ary :to_a
|
864
1285
|
|
865
1286
|
# Return true if `other` has the same type and contents as this `Vector`.
|
866
1287
|
#
|
@@ -915,8 +1336,12 @@ module Hamster
|
|
915
1336
|
root = [root].freeze
|
916
1337
|
levels += 1
|
917
1338
|
end
|
918
|
-
|
919
|
-
|
1339
|
+
new_root = update_leaf_node(root, levels * BITS_PER_LEVEL, index, item)
|
1340
|
+
if new_root.equal?(root)
|
1341
|
+
self
|
1342
|
+
else
|
1343
|
+
self.class.alloc(new_root, @size > index ? @size : index + 1, levels)
|
1344
|
+
end
|
920
1345
|
end
|
921
1346
|
|
922
1347
|
def update_leaf_node(node, bitshift, index, item)
|
@@ -925,7 +1350,12 @@ module Hamster
|
|
925
1350
|
old_child = node[slot_index] || []
|
926
1351
|
item = update_leaf_node(old_child, bitshift - BITS_PER_LEVEL, index, item)
|
927
1352
|
end
|
928
|
-
|
1353
|
+
existing_item = node[slot_index]
|
1354
|
+
if existing_item.equal?(item)
|
1355
|
+
node
|
1356
|
+
else
|
1357
|
+
node.dup.tap { |n| n[slot_index] = item }.freeze
|
1358
|
+
end
|
929
1359
|
end
|
930
1360
|
|
931
1361
|
def flatten_range(node, bitshift, from, to)
|
@@ -1082,9 +1512,10 @@ module Hamster
|
|
1082
1512
|
end
|
1083
1513
|
end
|
1084
1514
|
|
1085
|
-
# The canonical empty `Vector`. Returned by `
|
1515
|
+
# The canonical empty `Vector`. Returned by `Vector[]` when
|
1086
1516
|
# invoked with no arguments; also returned by `Vector.empty`. Prefer using this
|
1087
1517
|
# one rather than creating many empty vectors using `Vector.new`.
|
1088
1518
|
#
|
1519
|
+
# @private
|
1089
1520
|
EmptyVector = Hamster::Vector.empty
|
1090
1521
|
end
|