hamster 1.0.1.pre.rc3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/mutable_hash.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
-
require "forwardable"
|
2
1
|
require "hamster/hash"
|
3
2
|
require "hamster/read_copy_update"
|
4
3
|
|
5
4
|
module Hamster
|
6
|
-
|
7
|
-
MutableHash.new(hash(pairs, &block))
|
8
|
-
end
|
9
|
-
|
5
|
+
# @api private
|
10
6
|
class MutableHash
|
11
|
-
extend Forwardable
|
12
7
|
include ReadCopyUpdate
|
13
8
|
|
9
|
+
def self.[](pairs = {})
|
10
|
+
MutableHash.new(Hash[pairs])
|
11
|
+
end
|
12
|
+
|
14
13
|
def put(key, value = Undefined, &block)
|
15
14
|
transform { |hash| hash.put(key, value, &block) }
|
16
15
|
end
|
@@ -19,7 +18,7 @@ module Hamster
|
|
19
18
|
put(key, value)
|
20
19
|
value
|
21
20
|
end
|
22
|
-
|
21
|
+
alias :[]= :store
|
23
22
|
|
24
23
|
def delete(key)
|
25
24
|
old_value = nil
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require "set"
|
2
|
+
require "hamster/hash"
|
3
|
+
require "hamster/set"
|
4
|
+
require "hamster/vector"
|
5
|
+
require "hamster/sorted_set"
|
6
|
+
require "hamster/list"
|
7
|
+
require "hamster/deque"
|
8
|
+
require "hamster/core_ext/struct"
|
9
|
+
|
10
|
+
module Hamster
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# Create a Hamster immutable data structure with nested Hamster data
|
14
|
+
# structure from a nested Ruby object `obj`. This method recursively
|
15
|
+
# "walks" the Ruby object, converting Ruby `Hash` to {Hamster::Hash}, Ruby
|
16
|
+
# `Array` to {Hamster::Vector}, Ruby `Set` to {Hamster::Set}, and Ruby
|
17
|
+
# `SortedSet` to {Hamster::SortedSet}. Other objects are left as-is.
|
18
|
+
#
|
19
|
+
# @example
|
20
|
+
# h = Hamster.from({ "a" => [1, 2], "b" => "c" })
|
21
|
+
# # => Hamster::Hash["a" => Hamster::Vector[1, 2], "b" => "c"]
|
22
|
+
#
|
23
|
+
# @return [Hash, Vector, Set, SortedSet, Object]
|
24
|
+
def from(obj)
|
25
|
+
case obj
|
26
|
+
when ::Hash
|
27
|
+
res = obj.map { |key, value| [from(key), from(value)] }
|
28
|
+
Hamster::Hash.new(res)
|
29
|
+
when Hamster::Hash
|
30
|
+
obj.map { |key, value| [from(key), from(value)] }
|
31
|
+
when ::Struct
|
32
|
+
from(obj.to_h)
|
33
|
+
when ::Array
|
34
|
+
res = obj.map { |element| from(element) }
|
35
|
+
Hamster::Vector.new(res)
|
36
|
+
when ::SortedSet
|
37
|
+
# This clause must go before ::Set clause, since ::SortedSet is a ::Set.
|
38
|
+
res = obj.map { |element| from(element) }
|
39
|
+
Hamster::SortedSet.new(res)
|
40
|
+
when ::Set
|
41
|
+
res = obj.map { |element| from(element) }
|
42
|
+
Hamster::Set.new(res)
|
43
|
+
when Hamster::Vector, Hamster::Set, Hamster::SortedSet
|
44
|
+
obj.map { |element| from(element) }
|
45
|
+
else
|
46
|
+
obj
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Create a Ruby object from Hamster data. This method recursively "walks"
|
51
|
+
# the Hamster object, converting {Hamster::Hash} to Ruby `Hash`,
|
52
|
+
# {Hamster::Vector} and {Hamster::Deque} to Ruby `Array`, {Hamster::Set}
|
53
|
+
# to Ruby `Set`, and {Hamster::SortedSet} to Ruby `SortedSet`. Other
|
54
|
+
# objects are left as-is.
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# h = Hamster.to_ruby(Hamster.from({ "a" => [1, 2], "b" => "c" }))
|
58
|
+
# # => { "a" => [1, 2], "b" => "c" }
|
59
|
+
#
|
60
|
+
# @return [::Hash, ::Array, ::Set, ::SortedSet, Object]
|
61
|
+
def to_ruby(obj)
|
62
|
+
case obj
|
63
|
+
when Hamster::Hash, ::Hash
|
64
|
+
obj.each_with_object({}) { |keyval, hash| hash[to_ruby(keyval[0])] = to_ruby(keyval[1]) }
|
65
|
+
when Hamster::Vector, ::Array
|
66
|
+
obj.each_with_object([]) { |element, arr| arr << to_ruby(element) }
|
67
|
+
when Hamster::Set, ::Set
|
68
|
+
obj.each_with_object(::Set.new) { |element, set| set << to_ruby(element) }
|
69
|
+
when Hamster::SortedSet, ::SortedSet
|
70
|
+
obj.each_with_object(::SortedSet.new) { |element, set| set << to_ruby(element) }
|
71
|
+
when Hamster::Deque
|
72
|
+
obj.to_a.tap { |arr| arr.map! { |element| to_ruby(element) }}
|
73
|
+
else
|
74
|
+
obj
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/hamster/set.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
|
-
require "forwardable"
|
2
1
|
require "hamster/immutable"
|
3
2
|
require "hamster/undefined"
|
4
3
|
require "hamster/enumerable"
|
4
|
+
require "hamster/hash"
|
5
5
|
require "hamster/trie"
|
6
6
|
require "hamster/sorted_set"
|
7
|
+
require "set"
|
7
8
|
|
8
9
|
module Hamster
|
9
|
-
def self.set(*items)
|
10
|
-
items.empty? ? EmptySet : Set.new(items)
|
11
|
-
end
|
12
10
|
|
13
11
|
# `Hamster::Set` is a collection of unordered values with no duplicates. Testing whether
|
14
|
-
# an object is present in the `Set`
|
12
|
+
# an object is present in the `Set` can be done in constant time. `Set` is also `Enumerable`, so you can
|
15
13
|
# iterate over the members of the set with {#each}, transform them with {#map}, filter
|
16
14
|
# them with {#select}, and so on. Some of the `Enumerable` methods are overridden to
|
17
15
|
# return Hamster collections.
|
@@ -24,15 +22,13 @@ module Hamster
|
|
24
22
|
#
|
25
23
|
# `Set`s have no natural ordering and cannot be compared using `#<=>`. However, they
|
26
24
|
# define {#<}, {#>}, {#<=}, and {#>=} as shorthand for {#proper_subset?},
|
27
|
-
# {#proper_superset?}, {#subset?}, and {#superset?}
|
25
|
+
# {#proper_superset?}, {#subset?}, and {#superset?} respectively.
|
28
26
|
#
|
29
27
|
# The basic set-theoretic operations {#union}, {#intersection}, {#difference}, and
|
30
|
-
# {#exclusion} work with any `Enumerable` object.
|
31
|
-
# with another `Hamster::Set`, or a RubySet.
|
28
|
+
# {#exclusion} work with any `Enumerable` object.
|
32
29
|
#
|
33
|
-
# A `Set` can be created in
|
30
|
+
# A `Set` can be created in either of the following ways:
|
34
31
|
#
|
35
|
-
# Hamster.set('Tom', 'Dick', 'Harry')
|
36
32
|
# Hamster::Set.new([1, 2, 3]) # any Enumerable can be used to initialize
|
37
33
|
# Hamster::Set['A', 'B', 'C', 'D']
|
38
34
|
#
|
@@ -43,8 +39,7 @@ module Hamster
|
|
43
39
|
# actually return a new set and leave the existing one unchanged.
|
44
40
|
#
|
45
41
|
# @example
|
46
|
-
#
|
47
|
-
# set1 = Hamster.set(1, 2) # => Hamster::Set[1, 2]
|
42
|
+
# set1 = Hamster::Set[1, 2] # => Hamster::Set[1, 2]
|
48
43
|
# set2 = Hamster::Set[1, 2] # => Hamster::Set[1, 2]
|
49
44
|
# set1 == set2 # => true
|
50
45
|
# set3 = set1.add("foo") # => Hamster::Set[1, 2, "foo"]
|
@@ -53,7 +48,6 @@ module Hamster
|
|
53
48
|
# set1.subset?(set3) # => true
|
54
49
|
#
|
55
50
|
class Set
|
56
|
-
extend Forwardable
|
57
51
|
include Immutable
|
58
52
|
include Enumerable
|
59
53
|
|
@@ -61,7 +55,7 @@ module Hamster
|
|
61
55
|
# Create a new `Set` populated with the given items.
|
62
56
|
# @return [Set]
|
63
57
|
def [](*items)
|
64
|
-
new(items)
|
58
|
+
items.empty? ? empty : new(items)
|
65
59
|
end
|
66
60
|
|
67
61
|
# Return an empty `Set`. If used on a subclass, returns an empty instance
|
@@ -92,30 +86,35 @@ module Hamster
|
|
92
86
|
def empty?
|
93
87
|
@trie.empty?
|
94
88
|
end
|
95
|
-
def_delegator :self, :empty?, :null?
|
96
89
|
|
97
90
|
# Return the number of items in this `Set`.
|
98
91
|
# @return [Integer]
|
99
92
|
def size
|
100
93
|
@trie.size
|
101
94
|
end
|
102
|
-
|
95
|
+
alias :length :size
|
103
96
|
|
104
97
|
# Return a new `Set` with `item` added. If `item` is already in the set,
|
105
98
|
# return `self`.
|
106
99
|
#
|
100
|
+
# @example
|
101
|
+
# Hamster::Set[1, 2, 3].add(4) # => Hamster::Set[1, 2, 4, 3]
|
102
|
+
# Hamster::Set[1, 2, 3].add(2) # => Hamster::Set[1, 2, 3]
|
103
|
+
#
|
107
104
|
# @param item [Object] The object to add
|
108
105
|
# @return [Set]
|
109
106
|
def add(item)
|
110
107
|
include?(item) ? self : self.class.alloc(@trie.put(item, nil))
|
111
108
|
end
|
112
|
-
|
113
|
-
def_delegator :self, :add, :conj
|
114
|
-
def_delegator :self, :add, :conjoin
|
109
|
+
alias :<< :add
|
115
110
|
|
116
111
|
# If `item` is not a member of this `Set`, return a new `Set` with `item` added.
|
117
112
|
# Otherwise, return `false`.
|
118
113
|
#
|
114
|
+
# @example
|
115
|
+
# Hamster::Set[1, 2, 3].add?(4) # => Hamster::Set[1, 2, 4, 3]
|
116
|
+
# Hamster::Set[1, 2, 3].add?(2) # => false
|
117
|
+
#
|
119
118
|
# @param item [Object] The object to add
|
120
119
|
# @return [Set, false]
|
121
120
|
def add?(item)
|
@@ -125,22 +124,24 @@ module Hamster
|
|
125
124
|
# Return a new `Set` with `item` removed. If `item` is not a member of the set,
|
126
125
|
# return `self`.
|
127
126
|
#
|
127
|
+
# @example
|
128
|
+
# Hamster::Set[1, 2, 3].delete(1) # => Hamster::Set[2, 3]
|
129
|
+
# Hamster::Set[1, 2, 3].delete(99) # => Hamster::Set[1, 2, 3]
|
130
|
+
#
|
128
131
|
# @param item [Object] The object to remove
|
129
132
|
# @return [Set]
|
130
133
|
def delete(item)
|
131
134
|
trie = @trie.delete(item)
|
132
|
-
|
133
|
-
self
|
134
|
-
elsif trie.empty?
|
135
|
-
self.class.empty
|
136
|
-
else
|
137
|
-
self.class.alloc(trie)
|
138
|
-
end
|
135
|
+
new_trie(trie)
|
139
136
|
end
|
140
137
|
|
141
138
|
# If `item` is a member of this `Set`, return a new `Set` with `item` removed.
|
142
139
|
# Otherwise, return `false`.
|
143
140
|
#
|
141
|
+
# @example
|
142
|
+
# Hamster::Set[1, 2, 3].delete?(1) # => Hamster::Set[2, 3]
|
143
|
+
# Hamster::Set[1, 2, 3].delete?(99) # => false
|
144
|
+
#
|
144
145
|
# @param item [Object] The object to remove
|
145
146
|
# @return [Set, false]
|
146
147
|
def delete?(item)
|
@@ -148,9 +149,18 @@ module Hamster
|
|
148
149
|
end
|
149
150
|
|
150
151
|
# Call the block once for each item in this `Set`. No specific iteration order
|
151
|
-
# is guaranteed
|
152
|
+
# is guaranteed, but the order will be stable for any particular `Set`. If
|
153
|
+
# no block is given, an `Enumerator` is returned instead.
|
152
154
|
#
|
153
|
-
# @
|
155
|
+
# @example
|
156
|
+
# Hamster::Set["Dog", "Elephant", "Lion"].each { |e| puts e }
|
157
|
+
# Elephant
|
158
|
+
# Dog
|
159
|
+
# Lion
|
160
|
+
# # => Hamster::Set["Dog", "Elephant", "Lion"]
|
161
|
+
#
|
162
|
+
# @yield [item] Once for each item.
|
163
|
+
# @return [self, Enumerator]
|
154
164
|
def each
|
155
165
|
return to_enum if not block_given?
|
156
166
|
@trie.each { |key, _| yield(key) }
|
@@ -158,8 +168,17 @@ module Hamster
|
|
158
168
|
end
|
159
169
|
|
160
170
|
# Call the block once for each item in this `Set`. Iteration order will be
|
161
|
-
# the opposite of {#each}.
|
171
|
+
# the opposite of {#each}. If no block is given, an `Enumerator` is
|
172
|
+
# returned instead.
|
162
173
|
#
|
174
|
+
# @example
|
175
|
+
# Hamster::Set["Dog", "Elephant", "Lion"].reverse_each { |e| puts e }
|
176
|
+
# Lion
|
177
|
+
# Dog
|
178
|
+
# Elephant
|
179
|
+
# # => Hamster::Set["Dog", "Elephant", "Lion"]
|
180
|
+
#
|
181
|
+
# @yield [item] Once for each item.
|
163
182
|
# @return [self]
|
164
183
|
def reverse_each
|
165
184
|
return enum_for(:reverse_each) if not block_given?
|
@@ -169,65 +188,93 @@ module Hamster
|
|
169
188
|
|
170
189
|
# Return a new `Set` with all the items for which the block returns true.
|
171
190
|
#
|
191
|
+
# @example
|
192
|
+
# Hamster::Set["Elephant", "Dog", "Lion"].select { |e| e.size >= 4 }
|
193
|
+
# # => Hamster::Set["Elephant", "Lion"]
|
194
|
+
# @yield [item] Once for each item.
|
172
195
|
# @return [Set]
|
173
|
-
def
|
174
|
-
return enum_for(:
|
175
|
-
trie = @trie.
|
176
|
-
|
177
|
-
trie.equal?(@trie) ? self : self.class.alloc(trie)
|
196
|
+
def select
|
197
|
+
return enum_for(:select) unless block_given?
|
198
|
+
trie = @trie.select { |key, _| yield(key) }
|
199
|
+
new_trie(trie)
|
178
200
|
end
|
201
|
+
alias :find_all :select
|
202
|
+
alias :keep_if :select
|
179
203
|
|
180
|
-
|
181
|
-
|
182
|
-
#
|
183
|
-
# All the values returned from the block will be gathered into a new `Set`.
|
204
|
+
# Call the block once for each item in this `Set`. All the values returned
|
205
|
+
# from the block will be gathered into a new `Set`. If no block is given,
|
206
|
+
# an `Enumerator` is returned instead.
|
184
207
|
#
|
208
|
+
# @example
|
209
|
+
# Hamster::Set["Cat", "Elephant", "Dog", "Lion"].map { |e| e.size }
|
210
|
+
# # => Hamster::Set[8, 4, 3]
|
211
|
+
#
|
212
|
+
# @yield [item] Once for each item.
|
185
213
|
# @return [Set]
|
186
214
|
def map
|
187
215
|
return enum_for(:map) if not block_given?
|
188
216
|
return self if empty?
|
189
217
|
self.class.new(super)
|
190
218
|
end
|
191
|
-
|
219
|
+
alias :collect :map
|
192
220
|
|
193
221
|
# Return `true` if the given item is present in this `Set`. More precisely,
|
194
222
|
# return `true` if an object with the same `#hash` code, and which is also `#eql?`
|
195
223
|
# to the given object is present.
|
196
224
|
#
|
225
|
+
# @example
|
226
|
+
# Hamster::Set["A", "B", "C"].include?("B") # => true
|
227
|
+
# Hamster::Set["A", "B", "C"].include?("Z") # => false
|
228
|
+
#
|
197
229
|
# @param object [Object] The object to check for
|
198
230
|
# @return [Boolean]
|
199
231
|
def include?(object)
|
200
232
|
@trie.key?(object)
|
201
233
|
end
|
202
|
-
|
234
|
+
alias :member? :include?
|
203
235
|
|
204
236
|
# Return a member of this `Set`. The member chosen will be the first one which
|
205
237
|
# would be yielded by {#each}. If the set is empty, return `nil`.
|
206
238
|
#
|
239
|
+
# @example
|
240
|
+
# Hamster::Set["A", "B", "C"].first # => "C"
|
241
|
+
#
|
207
242
|
# @return [Object]
|
208
243
|
def first
|
209
244
|
(entry = @trie.at(0)) && entry[0]
|
210
245
|
end
|
211
|
-
def_delegator :self, :first, :head
|
212
246
|
|
213
247
|
# Return a {SortedSet} which contains the same items as this `Set`, ordered by
|
214
|
-
# the given comparator block.
|
215
|
-
# return 0, 1, or -1 depending on whether the first parameter is equal, greater than,
|
216
|
-
# or less than the second.
|
248
|
+
# the given comparator block.
|
217
249
|
#
|
218
|
-
# @
|
219
|
-
#
|
250
|
+
# @example
|
251
|
+
# Hamster::Set["Elephant", "Dog", "Lion"].sort
|
252
|
+
# # => Hamster::SortedSet["Dog", "Elephant", "Lion"]
|
253
|
+
# Hamster::Set["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
|
254
|
+
# # => Hamster::SortedSet["Dog", "Lion", "Elephant"]
|
255
|
+
#
|
256
|
+
# @yield [a, b] Any number of times with different pairs of elements.
|
257
|
+
# @yieldreturn [Integer] Negative if the first element should be sorted
|
258
|
+
# lower, positive if the latter element, or 0 if
|
259
|
+
# equal.
|
220
260
|
# @return [SortedSet]
|
221
261
|
def sort(&comparator)
|
222
262
|
SortedSet.new(self.to_a, &comparator)
|
223
263
|
end
|
224
264
|
|
225
|
-
# Return a {SortedSet} which contains the same items as this `Set`, ordered
|
226
|
-
# mapping each item through the provided block to obtain sort keys, and
|
227
|
-
# sorting the keys.
|
265
|
+
# Return a {SortedSet} which contains the same items as this `Set`, ordered
|
266
|
+
# by mapping each item through the provided block to obtain sort keys, and
|
267
|
+
# then sorting the keys.
|
228
268
|
#
|
229
|
-
# @
|
230
|
-
#
|
269
|
+
# @example
|
270
|
+
# Hamster::Set["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
|
271
|
+
# # => Hamster::SortedSet["Dog", "Lion", "Elephant"]
|
272
|
+
#
|
273
|
+
# @yield [item] Once for each item to create the set, and then potentially
|
274
|
+
# again depending on what operations are performed on the
|
275
|
+
# returned {SortedSet}. As such, it is recommended that the
|
276
|
+
# block be a pure function.
|
277
|
+
# @yieldreturn [Object] sort key for the item
|
231
278
|
# @return [SortedSet]
|
232
279
|
def sort_by(&mapper)
|
233
280
|
SortedSet.new(self.to_a, &mapper)
|
@@ -242,22 +289,29 @@ module Hamster
|
|
242
289
|
# @param other [Enumerable] The collection to merge with
|
243
290
|
# @return [Set]
|
244
291
|
def union(other)
|
245
|
-
if other.is_a?(Hamster::Set)
|
246
|
-
|
247
|
-
|
292
|
+
if other.is_a?(Hamster::Set)
|
293
|
+
if other.size > size
|
294
|
+
small_set_pairs = @trie
|
295
|
+
large_set_trie = other.instance_variable_get(:@trie)
|
296
|
+
else
|
297
|
+
small_set_pairs = other.instance_variable_get(:@trie)
|
298
|
+
large_set_trie = @trie
|
299
|
+
end
|
248
300
|
else
|
249
|
-
|
301
|
+
if other.respond_to?(:lazy)
|
302
|
+
small_set_pairs = other.lazy.map { |e| [e, nil] }
|
303
|
+
else
|
304
|
+
small_set_pairs = other.map { |e| [e, nil] }
|
305
|
+
end
|
250
306
|
large_set_trie = @trie
|
251
307
|
end
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
end
|
256
|
-
trie.equal?(@trie) ? self : self.class.alloc(trie)
|
308
|
+
|
309
|
+
trie = large_set_trie.bulk_put(small_set_pairs)
|
310
|
+
new_trie(trie)
|
257
311
|
end
|
258
|
-
|
259
|
-
|
260
|
-
|
312
|
+
alias :| :union
|
313
|
+
alias :+ :union
|
314
|
+
alias :merge :union
|
261
315
|
|
262
316
|
# Return a new `Set` which contains all the items which are members of both
|
263
317
|
# this `Set` and `other`. `other` can be any `Enumerable` object.
|
@@ -268,15 +322,19 @@ module Hamster
|
|
268
322
|
# @param other [Enumerable] The collection to intersect with
|
269
323
|
# @return [Set]
|
270
324
|
def intersection(other)
|
271
|
-
if
|
272
|
-
|
325
|
+
if other.size < @trie.size
|
326
|
+
if other.is_a?(Hamster::Set)
|
327
|
+
trie = other.instance_variable_get(:@trie).select { |key, _| include?(key) }
|
328
|
+
else
|
329
|
+
trie = Trie.new(0)
|
330
|
+
other.each { |obj| trie.put!(obj, nil) if include?(obj) }
|
331
|
+
end
|
273
332
|
else
|
274
|
-
trie = @trie.
|
333
|
+
trie = @trie.select { |key, _| other.include?(key) }
|
275
334
|
end
|
276
|
-
|
335
|
+
new_trie(trie)
|
277
336
|
end
|
278
|
-
|
279
|
-
def_delegator :self, :intersection, :&
|
337
|
+
alias :& :intersection
|
280
338
|
|
281
339
|
# Return a new `Set` with all the items in `other` removed. `other` can be
|
282
340
|
# any `Enumerable` object.
|
@@ -288,15 +346,14 @@ module Hamster
|
|
288
346
|
# @return [Set]
|
289
347
|
def difference(other)
|
290
348
|
trie = if (@trie.size <= other.size) && (other.is_a?(Hamster::Set) || (defined?(::Set) && other.is_a?(::Set)))
|
291
|
-
@trie.
|
349
|
+
@trie.select { |key, _| !other.include?(key) }
|
292
350
|
else
|
293
|
-
|
351
|
+
@trie.bulk_delete(other)
|
294
352
|
end
|
295
|
-
|
353
|
+
new_trie(trie)
|
296
354
|
end
|
297
|
-
|
298
|
-
|
299
|
-
def_delegator :self, :difference, :-
|
355
|
+
alias :subtract :difference
|
356
|
+
alias :- :difference
|
300
357
|
|
301
358
|
# Return a new `Set` which contains all the items which are members of this
|
302
359
|
# `Set` or of `other`, but not both. `other` can be any `Enumerable` object.
|
@@ -309,20 +366,39 @@ module Hamster
|
|
309
366
|
def exclusion(other)
|
310
367
|
((self | other) - (self & other))
|
311
368
|
end
|
312
|
-
|
369
|
+
alias :^ :exclusion
|
313
370
|
|
314
371
|
# Return `true` if all items in this `Set` are also in `other`.
|
315
372
|
#
|
373
|
+
# @example
|
374
|
+
# Hamster::Set[2, 3].subset?(Hamster::Set[1, 2, 3]) # => true
|
375
|
+
#
|
316
376
|
# @param other [Set]
|
317
377
|
# @return [Boolean]
|
318
378
|
def subset?(other)
|
319
379
|
return false if other.size < size
|
380
|
+
|
381
|
+
# This method has the potential to be very slow if 'other' is a large Array, so to avoid that,
|
382
|
+
# we convert those Arrays to Sets before checking presence of items
|
383
|
+
# Time to convert Array -> Set is linear in array.size
|
384
|
+
# Time to check for presence of all items in an Array is proportional to set.size * array.size
|
385
|
+
# Note that both sides of that equation have array.size -- hence those terms cancel out,
|
386
|
+
# and the break-even point is solely dependent on the size of this collection
|
387
|
+
# After doing some benchmarking to estimate the constants, it appears break-even is at ~190 items
|
388
|
+
# We also check other.size, to avoid the more expensive #is_a? checks in cases where it doesn't matter
|
389
|
+
#
|
390
|
+
if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
|
391
|
+
other = ::Set.new(other)
|
392
|
+
end
|
320
393
|
all? { |item| other.include?(item) }
|
321
394
|
end
|
322
395
|
alias :<= :subset?
|
323
396
|
|
324
397
|
# Return `true` if all items in `other` are also in this `Set`.
|
325
398
|
#
|
399
|
+
# @example
|
400
|
+
# Hamster::Set[1, 2, 3].superset?(Hamster::Set[2, 3]) # => true
|
401
|
+
#
|
326
402
|
# @param other [Set]
|
327
403
|
# @return [Boolean]
|
328
404
|
def superset?(other)
|
@@ -333,10 +409,18 @@ module Hamster
|
|
333
409
|
# Returns `true` if `other` contains all the items in this `Set`, plus at least
|
334
410
|
# one item which is not in this set.
|
335
411
|
#
|
412
|
+
# @example
|
413
|
+
# Hamster::Set[2, 3].proper_subset?(Hamster::Set[1, 2, 3]) # => true
|
414
|
+
# Hamster::Set[1, 2, 3].proper_subset?(Hamster::Set[1, 2, 3]) # => false
|
415
|
+
#
|
336
416
|
# @param other [Set]
|
337
417
|
# @return [Boolean]
|
338
418
|
def proper_subset?(other)
|
339
419
|
return false if other.size <= size
|
420
|
+
# See comments above
|
421
|
+
if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
|
422
|
+
other = ::Set.new(other)
|
423
|
+
end
|
340
424
|
all? { |item| other.include?(item) }
|
341
425
|
end
|
342
426
|
alias :< :proper_subset?
|
@@ -344,6 +428,10 @@ module Hamster
|
|
344
428
|
# Returns `true` if this `Set` contains all the items in `other`, plus at least
|
345
429
|
# one item which is not in `other`.
|
346
430
|
#
|
431
|
+
# @example
|
432
|
+
# Hamster::Set[1, 2, 3].proper_superset?(Hamster::Set[2, 3]) # => true
|
433
|
+
# Hamster::Set[1, 2, 3].proper_superset?(Hamster::Set[1, 2, 3]) # => false
|
434
|
+
#
|
347
435
|
# @param other [Set]
|
348
436
|
# @return [Boolean]
|
349
437
|
def proper_superset?(other)
|
@@ -353,19 +441,29 @@ module Hamster
|
|
353
441
|
|
354
442
|
# Return `true` if this `Set` and `other` do not share any items.
|
355
443
|
#
|
444
|
+
# @example
|
445
|
+
# Hamster::Set[1, 2].disjoint?(Hamster::Set[8, 9]) # => true
|
446
|
+
#
|
356
447
|
# @param other [Set]
|
357
448
|
# @return [Boolean]
|
358
449
|
def disjoint?(other)
|
359
|
-
if size
|
360
|
-
each { |item| return false if other.include?(item) }
|
361
|
-
else
|
450
|
+
if other.size <= size
|
362
451
|
other.each { |item| return false if include?(item) }
|
452
|
+
else
|
453
|
+
# See comment on #subset?
|
454
|
+
if other.size >= 150 && @trie.size >= 190 && !(other.is_a?(Hamster::Set) || other.is_a?(::Set))
|
455
|
+
other = ::Set.new(other)
|
456
|
+
end
|
457
|
+
each { |item| return false if other.include?(item) }
|
363
458
|
end
|
364
459
|
true
|
365
460
|
end
|
366
461
|
|
367
462
|
# Return `true` if this `Set` and `other` have at least one item in common.
|
368
463
|
#
|
464
|
+
# @example
|
465
|
+
# Hamster::Set[1, 2].intersect?(Hamster::Set[2, 3]) # => true
|
466
|
+
#
|
369
467
|
# @param other [Set]
|
370
468
|
# @return [Boolean]
|
371
469
|
def intersect?(other)
|
@@ -387,11 +485,14 @@ module Hamster
|
|
387
485
|
end
|
388
486
|
end
|
389
487
|
|
390
|
-
|
391
|
-
|
488
|
+
alias :group :group_by
|
489
|
+
alias :classify :group_by
|
392
490
|
|
393
491
|
# Return a randomly chosen item from this `Set`. If the set is empty, return `nil`.
|
394
492
|
#
|
493
|
+
# @example
|
494
|
+
# Hamster::Set[1, 2, 3, 4, 5].sample # => 3
|
495
|
+
#
|
395
496
|
# @return [Object]
|
396
497
|
def sample
|
397
498
|
empty? ? nil : @trie.at(rand(size))[0]
|
@@ -400,7 +501,7 @@ module Hamster
|
|
400
501
|
# Return an empty `Set` instance, of the same class as this one. Useful if you
|
401
502
|
# have multiple subclasses of `Set` and want to treat them polymorphically.
|
402
503
|
#
|
403
|
-
# @return [
|
504
|
+
# @return [Set]
|
404
505
|
def clear
|
405
506
|
self.class.empty
|
406
507
|
end
|
@@ -419,7 +520,7 @@ module Hamster
|
|
419
520
|
end
|
420
521
|
true
|
421
522
|
end
|
422
|
-
|
523
|
+
alias :== :eql?
|
423
524
|
|
424
525
|
# See `Object#hash`.
|
425
526
|
# @return [Integer]
|
@@ -430,10 +531,6 @@ module Hamster
|
|
430
531
|
undef :"<=>" # Sets are not ordered, so Enumerable#<=> will give a meaningless result
|
431
532
|
undef :each_index # Set members cannot be accessed by 'index', so #each_index is not meaningful
|
432
533
|
|
433
|
-
def_delegator :self, :dup, :uniq
|
434
|
-
def_delegator :self, :dup, :nub
|
435
|
-
def_delegator :self, :dup, :remove_duplicates
|
436
|
-
|
437
534
|
# Return `self`.
|
438
535
|
#
|
439
536
|
# @return [self]
|
@@ -456,11 +553,24 @@ module Hamster
|
|
456
553
|
trie.put(key_value.first, nil)
|
457
554
|
end
|
458
555
|
end
|
556
|
+
|
557
|
+
private
|
558
|
+
|
559
|
+
def new_trie(trie)
|
560
|
+
if trie.empty?
|
561
|
+
self.class.empty
|
562
|
+
elsif trie.equal?(@trie)
|
563
|
+
self
|
564
|
+
else
|
565
|
+
self.class.alloc(trie)
|
566
|
+
end
|
567
|
+
end
|
459
568
|
end
|
460
569
|
|
461
|
-
# The canonical empty `Set`. Returned by `
|
570
|
+
# The canonical empty `Set`. Returned by `Set[]` when
|
462
571
|
# invoked with no arguments; also returned by `Set.empty`. Prefer using this
|
463
572
|
# one rather than creating many empty sets using `Set.new`.
|
464
573
|
#
|
574
|
+
# @private
|
465
575
|
EmptySet = Hamster::Set.empty
|
466
576
|
end
|