Class: Hamster::Vector
- Inherits:
-
Object
- Object
- Hamster::Vector
- Includes:
- Associable, Enumerable, Immutable
- Defined in:
- lib/hamster/vector.rb
Overview
A ‘Vector` is an ordered, integer-indexed collection of objects. Like Ruby’s ‘Array`, `Vector` indexing starts at zero and negative indexes count back from the end.
‘Vector` has a similar interface to `Array`. The main difference is methods that would destructively update an `Array` (such as #insert or #delete_at) instead return new `Vectors` and leave the existing one unchanged.
### Creating New Vectors
Hamster::Vector.new([:first, :second, :third])
Hamster::Vector[1, 2, 3, 4, 5]
### Retrieving Items from Vectors
vector = Hamster::Vector[1, 2, 3, 4, 5]
vector[0] # => 1
vector[-1] # => 5
vector[0,3] # => Hamster::Vector[1, 2, 3]
vector[1..-1] # => Hamster::Vector[2, 3, 4, 5]
vector.first # => 1
vector.last # => 5
### Creating Modified Vectors
vector.add(6) # => Hamster::Vector[1, 2, 3, 4, 5, 6]
vector.insert(1, :a, :b) # => Hamster::Vector[1, :a, :b, 2, 3, 4, 5]
vector.delete_at(2) # => Hamster::Vector[1, 2, 4, 5]
vector + [6, 7] # => Hamster::Vector[1, 2, 3, 4, 5, 6, 7]
Constant Summary collapse
- BLOCK_SIZE =
32
- INDEX_MASK =
BLOCK_SIZE - 1
- BITS_PER_LEVEL =
5
Instance Attribute Summary collapse
-
#size ⇒ Integer
(also: #length)
readonly
Return the number of items in this ‘Vector`.
Class Method Summary collapse
-
.[](*items) ⇒ Vector
Create a new ‘Vector` populated with the given items.
-
.alloc(root, size, levels) ⇒ Vector
“Raw” allocation of a new ‘Vector`.
-
.empty ⇒ Vector
Return an empty ‘Vector`.
Instance Method Summary collapse
-
#*(times) ⇒ Vector
Repetition.
-
#+(other) ⇒ Vector
(also: #concat)
Return a new ‘Vector` built by concatenating this one with `other`.
-
#add(item) ⇒ Vector
(also: #<<, #push)
Return a new ‘Vector` with `item` added after the last occupied position.
-
#assoc(obj) ⇒ Object
Assumes all elements are nested, indexable collections, and searches through them, comparing ‘obj` with the first element of each nested collection.
-
#bsearch {|element| ... } ⇒ Object
Finds a value from this ‘Vector` which meets the condition defined by the provided block, using a binary search.
-
#clear ⇒ Vector
Return an empty ‘Vector` instance, of the same class as this one.
-
#combination(n) ⇒ self, Enumerator
When invoked with a block, yields all combinations of length ‘n` of items from the `Vector`, and then returns `self`.
-
#delete(obj) ⇒ Vector
Return a new ‘Vector` with all items which are equal to `obj` removed.
-
#delete_at(index) ⇒ Vector
Return a new ‘Vector` with the element at `index` removed.
-
#drop(n) ⇒ Vector
Drop the first ‘n` elements and return the rest in a new `Vector`.
-
#drop_while ⇒ Vector, Enumerator
Drop elements up to, but not including, the first element for which the block returns ‘nil` or `false`.
-
#each(&block) ⇒ self, Enumerator
Call the given block once for each item in the vector, passing each item from first to last successively to the block.
-
#empty? ⇒ Boolean
Return ‘true` if this `Vector` contains no items.
-
#eql?(other) ⇒ Boolean
Return true if ‘other` has the same type and contents as this `Vector`.
-
#fetch(index, default = (missing_default = true)) ⇒ Object
Retrieve the value at ‘index` with optional default.
-
#fill(object, index = 0, length = nil) ⇒ Vector
Replace a range of indexes with the given object.
-
#first ⇒ Object
Return the first item in the ‘Vector`.
-
#flat_map ⇒ Vector
Return a new ‘Vector` with the concatenated results of running the block once for every element in this `Vector`.
-
#flatten(level = -1)) ⇒ Vector
Return a new ‘Vector` with all nested vectors and arrays recursively “flattened out”.
-
#get(index) ⇒ Object
(also: #at)
Retrieve the item at ‘index`.
-
#hash ⇒ Integer
See ‘Object#hash`.
-
#initialize(items = [].freeze) ⇒ Vector
constructor
A new instance of Vector.
-
#insert(index, *items) ⇒ Vector
Return a new ‘Vector` with the given values inserted before the element at `index`.
-
#last ⇒ Object
Return the last item in the ‘Vector`.
-
#map ⇒ Vector, Enumerator
(also: #collect)
Invoke the given block once for each item in the vector, and return a new ‘Vector` containing the values returned by the block.
- #marshal_dump ⇒ ::Array
- #marshal_load(array) ⇒ Object
-
#permutation(n = @size) ⇒ self, Enumerator
Yields all permutations of length ‘n` of items from the `Vector`, and then returns `self`.
-
#pop ⇒ Vector
Return a new ‘Vector` with the last element removed.
-
#product(*vectors) ⇒ Vector
Cartesian product or multiplication.
-
#put(index, item = yield(get(index))) ⇒ Vector
(also: #set)
Return a new ‘Vector` with a new value at the given `index`.
-
#rassoc(obj) ⇒ Object
Assumes all elements are nested, indexable collections, and searches through them, comparing ‘obj` with the second element of each nested collection.
-
#repeated_combination(n) ⇒ self, Enumerator
When invoked with a block, yields all repeated combinations of length ‘n` of items from the `Vector`, and then returns `self`.
-
#repeated_permutation(n = @size) ⇒ self, Enumerator
When invoked with a block, yields all repeated permutations of length ‘n` of items from the `Vector`, and then returns `self`.
-
#reverse ⇒ Vector
Return a new ‘Vector` with the same elements as this one, but in reverse order.
-
#reverse_each(&block) ⇒ self
Call the given block once for each item in the vector, from last to first.
-
#rindex(obj = (missing_arg = true)) ⇒ Integer
Find the index of an element, starting from the end of the vector.
-
#rotate(count = 1) ⇒ Vector
Return a new ‘Vector` with the same elements, but rotated so that the one at index `count` is the first element of the new vector.
-
#sample ⇒ Object
Return a randomly chosen item from this ‘Vector`.
-
#select {|element| ... } ⇒ Vector
(also: #find_all, #keep_if)
Return a new ‘Vector` containing all elements for which the given block returns true.
-
#shift ⇒ Vector
Return a new ‘Vector` with the first element removed.
-
#shuffle ⇒ Vector
Return a new ‘Vector` with the same elements as this one, but randomly permuted.
-
#slice(arg, length = (missing_length = true)) ⇒ Object
(also: #[])
Return specific objects from the ‘Vector`.
-
#sort ⇒ Vector
Return a new ‘Vector` with the same items, but sorted.
-
#sort_by {|element| ... } ⇒ Vector
Return a new ‘Vector` with the same items, but sorted.
-
#take(n) ⇒ Vector
Return only the first ‘n` elements in a new `Vector`.
-
#take_while ⇒ Vector, Enumerator
Gather elements up to, but not including, the first element for which the block returns ‘nil` or `false`, and return them in a new `Vector`.
-
#to_a ⇒ Array
(also: #to_ary)
Return an ‘Array` with the same elements, in the same order.
-
#transpose ⇒ Vector
Assume all elements are vectors or arrays and transpose the rows and columns.
-
#uniq(&block) ⇒ Vector
Return a new ‘Vector` with no duplicate elements, as determined by `#hash` and `#eql?`.
-
#unshift(object) ⇒ Vector
Return a new ‘Vector` with `object` inserted before the first element, moving the other elements upwards.
-
#values_at(*indices) ⇒ Vector
Return a new ‘Vector` with only the elements at the given `indices`, in the order specified by `indices`.
-
#zip(*others) ⇒ Vector
Combine two vectors by “zipping” them together.
Methods included from Associable
Methods included from Enumerable
#<=>, #==, #compact, #each_index, #grep, #grep_v, #group_by, #inspect, #join, #partition, #pretty_print, #reject, #sum, #to_set
Methods included from Enumerable
Methods included from Immutable
Constructor Details
#initialize(items = [].freeze) ⇒ Vector
Returns a new instance of Vector.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/hamster/vector.rb', line 85 def initialize(items=[].freeze) items = items.to_a if items.size <= 32 items = items.dup.freeze if !items.frozen? @root, @size, @levels = items, items.size, 0 else root, size, levels = items, items.size, 0 while root.size > 32 root = root.each_slice(32).to_a levels += 1 end @root, @size, @levels = root.freeze, size, levels end end |
Instance Attribute Details
#size ⇒ Integer (readonly) Also known as: length
Return the number of items in this ‘Vector`
53 54 55 |
# File 'lib/hamster/vector.rb', line 53 def size @size end |
Class Method Details
.[](*items) ⇒ Vector
Create a new ‘Vector` populated with the given items.
59 60 61 |
# File 'lib/hamster/vector.rb', line 59 def [](*items) new(items.freeze) end |
.alloc(root, size, levels) ⇒ Vector
“Raw” allocation of a new ‘Vector`. Used internally to create a new instance quickly after building a modified trie.
76 77 78 79 80 81 82 |
# File 'lib/hamster/vector.rb', line 76 def alloc(root, size, levels) obj = allocate obj.instance_variable_set(:@root, root) obj.instance_variable_set(:@size, size) obj.instance_variable_set(:@levels, levels) obj end |
.empty ⇒ Vector
Return an empty ‘Vector`. If used on a subclass, returns an empty instance of that class.
67 68 69 |
# File 'lib/hamster/vector.rb', line 67 def empty @empty ||= self.new end |
Instance Method Details
#*(times) ⇒ Vector
Repetition. Return a new ‘Vector` built by concatenating `times` copies of this one together.
758 759 760 761 762 763 |
# File 'lib/hamster/vector.rb', line 758 def *(times) return self.class.empty if times == 0 return self if times == 1 result = (to_a * times) result.is_a?(Array) ? self.class.new(result) : result end |
#+(other) ⇒ Vector Also known as: concat
Return a new ‘Vector` built by concatenating this one with `other`. `other` can be any object which is convertible to an `Array` using `#to_a`.
611 612 613 614 615 |
# File 'lib/hamster/vector.rb', line 611 def +(other) other = other.to_a other = other.dup if other.frozen? replace_suffix(@size, other) end |
#add(item) ⇒ Vector Also known as: <<, push
Return a new ‘Vector` with `item` added after the last occupied position.
134 135 136 |
# File 'lib/hamster/vector.rb', line 134 def add(item) update_root(@size, item) end |
#assoc(obj) ⇒ Object
Assumes all elements are nested, indexable collections, and searches through them, comparing ‘obj` with the first element of each nested collection. Return the first nested collection which matches, or `nil` if none is found. Behaviour is undefined when elements do not meet assumptions (i.e. are not indexable collections).
1243 1244 1245 1246 1247 1248 1249 |
# File 'lib/hamster/vector.rb', line 1243 def assoc(obj) each do |array| next if !array.respond_to?(:[]) return array if obj == array[0] end nil end |
#bsearch {|element| ... } ⇒ Object
Finds a value from this ‘Vector` which meets the condition defined by the provided block, using a binary search. The vector must already be sorted with respect to the block. See Ruby’s ‘Array#bsearch` for details, behaviour is equivalent.
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 |
# File 'lib/hamster/vector.rb', line 1137 def bsearch return enum_for(:bsearch) if not block_given? low, high, result = 0, @size, nil while low < high mid = (low + ((high - low) >> 1)) val = get(mid) v = yield val if v.is_a? Numeric if v == 0 return val elsif v > 0 high = mid else low = mid + 1 end elsif v == true result = val high = mid elsif !v low = mid + 1 else raise TypeError, "wrong argument type #{v.class} (must be numeric, true, false, or nil)" end end result end |
#clear ⇒ Vector
Return an empty ‘Vector` instance, of the same class as this one. Useful if you have multiple subclasses of `Vector` and want to treat them polymorphically.
1168 1169 1170 |
# File 'lib/hamster/vector.rb', line 1168 def clear self.class.empty end |
#combination(n) ⇒ self, Enumerator
When invoked with a block, yields all combinations of length ‘n` of items from the `Vector`, and then returns `self`. There is no guarantee about which order the combinations will be yielded.
If no block is given, an ‘Enumerator` is returned instead.
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 |
# File 'lib/hamster/vector.rb', line 837 def combination(n) return enum_for(:combination, n) if not block_given? return self if n < 0 || @size < n if n == 0 yield [] elsif n == 1 each { |item| yield [item] } elsif n == @size yield self.to_a else combos = lambda do |result,index,remaining| while @size - index > remaining if remaining == 1 yield result.dup << get(index) else combos[result.dup << get(index), index+1, remaining-1] end index += 1 end index.upto(@size-1) { |i| result << get(i) } yield result end combos[[], 0, n] end self end |
#delete(obj) ⇒ Vector
Return a new ‘Vector` with all items which are equal to `obj` removed. `#==` is used for checking equality.
476 477 478 |
# File 'lib/hamster/vector.rb', line 476 def delete(obj) select { |item| item != obj } end |
#delete_at(index) ⇒ Vector
Return a new ‘Vector` with the element at `index` removed. If the given `index` does not exist, return `self`.
372 373 374 375 376 377 378 |
# File 'lib/hamster/vector.rb', line 372 def delete_at(index) return self if index >= @size || index < -@size index += @size if index < 0 suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, []) replace_suffix(index, suffix.tap { |a| a.shift }) end |
#drop(n) ⇒ Vector
Drop the first ‘n` elements and return the rest in a new `Vector`.
701 702 703 704 705 706 |
# File 'lib/hamster/vector.rb', line 701 def drop(n) return self if n == 0 return self.class.empty if n >= @size raise ArgumentError, "attempt to drop negative size" if n < 0 self.class.new(flatten_suffix(@root, @levels * BITS_PER_LEVEL, n, [])) end |
#drop_while ⇒ Vector, Enumerator
Drop elements up to, but not including, the first element for which the block returns ‘nil` or `false`. Gather the remaining elements into a new `Vector`. If no block is given, an `Enumerator` is returned instead.
730 731 732 733 |
# File 'lib/hamster/vector.rb', line 730 def drop_while return enum_for(:drop_while) if not block_given? self.class.new(super) end |
#each(&block) ⇒ self, Enumerator
Call the given block once for each item in the vector, passing each item from first to last successively to the block. If no block is given, an ‘Enumerator` is returned instead.
429 430 431 432 433 |
# File 'lib/hamster/vector.rb', line 429 def each(&block) return to_enum unless block_given? traverse_depth_first(@root, @levels, &block) self end |
#empty? ⇒ Boolean
Return ‘true` if this `Vector` contains no items.
103 104 105 |
# File 'lib/hamster/vector.rb', line 103 def empty? @size == 0 end |
#eql?(other) ⇒ Boolean
Return true if ‘other` has the same type and contents as this `Vector`.
1290 1291 1292 1293 1294 |
# File 'lib/hamster/vector.rb', line 1290 def eql?(other) return true if other.equal?(self) return false unless instance_of?(other.class) && @size == other.size @root.eql?(other.instance_variable_get(:@root)) end |
#fetch(index) ⇒ Object #fetch(index) {|index| ... } ⇒ Object #fetch(index, default) ⇒ Object
Retrieve the value at ‘index` with optional default.
260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/hamster/vector.rb', line 260 def fetch(index, default = (missing_default = true)) if index >= -@size && index < @size get(index) elsif block_given? yield(index) elsif !missing_default default else raise IndexError, "index #{index} outside of vector bounds" end end |
#fill(object) ⇒ Vector #fill(object, index) ⇒ Vector #fill(object, index, length) ⇒ Vector
Replace a range of indexes with the given object.
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 |
# File 'lib/hamster/vector.rb', line 802 def fill(object, index = 0, length = nil) raise IndexError if index < -@size index += @size if index < 0 length ||= @size - index # to the end of the array, if no length given if index < @size suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, []) suffix.fill(object, 0, length) elsif index == @size suffix = Array.new(length, object) else suffix = Array.new(index - @size, nil).concat(Array.new(length, object)) index = @size end replace_suffix(index, suffix) end |
#first ⇒ Object
Return the first item in the ‘Vector`. If the vector is empty, return `nil`.
113 114 115 |
# File 'lib/hamster/vector.rb', line 113 def first get(0) end |
#flat_map ⇒ Vector
Return a new ‘Vector` with the concatenated results of running the block once for every element in this `Vector`.
503 504 505 506 507 |
# File 'lib/hamster/vector.rb', line 503 def flat_map return enum_for(:flat_map) if not block_given? return self if empty? self.class.new(super) end |
#flatten(level = -1)) ⇒ Vector
Return a new ‘Vector` with all nested vectors and arrays recursively “flattened out”. That is, their elements inserted into the new `Vector` in the place where the nested array/vector originally was. If an optional `level` argument is provided, the flattening will only be done recursively that number of times. A `level` of 0 means not to flatten at all, 1 means to only flatten nested arrays/vectors which are directly contained within this `Vector`.
590 591 592 593 594 595 596 597 598 599 600 |
# File 'lib/hamster/vector.rb', line 590 def flatten(level = -1) return self if level == 0 array = self.to_a if array.frozen? self.class.new(array.flatten(level).freeze) elsif array.flatten!(level) # returns nil if no changes were made self.class.new(array.freeze) else self end end |
#get(index) ⇒ Object Also known as: at
Retrieve the item at ‘index`. If there is none (either the provided index is too high or too low), return `nil`.
213 214 215 216 217 218 |
# File 'lib/hamster/vector.rb', line 213 def get(index) return nil if @size == 0 index += @size if index < 0 return nil if index >= @size || index < 0 leaf_node_for(@root, @levels * BITS_PER_LEVEL, index)[index & INDEX_MASK] end |
#hash ⇒ Integer
See ‘Object#hash`.
1298 1299 1300 |
# File 'lib/hamster/vector.rb', line 1298 def hash reduce(0) { |hash, item| (hash << 5) - hash + item.hash } end |
#insert(index, *items) ⇒ Vector
Return a new ‘Vector` with the given values inserted before the element at `index`. If `index` is greater than the current length, `nil` values are added to pad the `Vector` to the required size.
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 |
# File 'lib/hamster/vector.rb', line 346 def insert(index, *items) raise IndexError if index < -@size index += @size if index < 0 if index < @size suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, []) suffix.unshift(*items) elsif index == @size suffix = items else suffix = Array.new(index - @size, nil).concat(items) index = @size end replace_suffix(index, suffix) end |
#last ⇒ Object
Return the last item in the ‘Vector`. If the vector is empty, return `nil`.
123 124 125 |
# File 'lib/hamster/vector.rb', line 123 def last get(-1) end |
#map ⇒ Vector, Enumerator Also known as: collect
Invoke the given block once for each item in the vector, and return a new ‘Vector` containing the values returned by the block. If no block is provided, return an enumerator.
488 489 490 491 492 |
# File 'lib/hamster/vector.rb', line 488 def map return enum_for(:map) if not block_given? return self if empty? self.class.new(super) end |
#marshal_dump ⇒ ::Array
1304 1305 1306 |
# File 'lib/hamster/vector.rb', line 1304 def marshal_dump to_a end |
#marshal_load(array) ⇒ Object
1309 1310 1311 |
# File 'lib/hamster/vector.rb', line 1309 def marshal_load(array) initialize(array.freeze) end |
#permutation(n = @size) ⇒ self, Enumerator
Yields all permutations of length ‘n` of items from the `Vector`, and then returns `self`. If no length `n` is specified, permutations of all elements will be yielded.
There is no guarantee about which order the permutations will be yielded in.
If no block is given, an ‘Enumerator` is returned instead.
940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 |
# File 'lib/hamster/vector.rb', line 940 def permutation(n = @size) return enum_for(:permutation, n) if not block_given? if n < 0 || @size < n # yield nothing elsif n == 0 yield [] elsif n == 1 each { |item| yield [item] } else used, result = [], [] perms = lambda do |index| 0.upto(@size-1) do |i| if !used[i] result[index] = get(i) if index < n-1 used[i] = true perms[index+1] used[i] = false else yield result.dup end end end end perms[0] end self end |
#pop ⇒ Vector
Return a new ‘Vector` with the last element removed. Return `self` if empty.
387 388 389 390 |
# File 'lib/hamster/vector.rb', line 387 def pop return self if @size == 0 replace_suffix(@size-1, []) end |
#product(*vectors) ⇒ Vector #product ⇒ Vector
Cartesian product or multiplication.
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 |
# File 'lib/hamster/vector.rb', line 1038 def product(*vectors) # if no vectors passed, return "product" as in result of multiplying all items return super if vectors.empty? vectors.unshift(self) if vectors.any?(&:empty?) return block_given? ? self : [] end counters = Array.new(vectors.size, 0) bump_counters = lambda do i = vectors.size-1 counters[i] += 1 while counters[i] == vectors[i].size counters[i] = 0 i -= 1 return true if i == -1 # we are done counters[i] += 1 end false # not done yet end build_array = lambda do array = [] counters.each_with_index { |index,i| array << vectors[i][index] } array end if block_given? while true yield build_array[] return self if bump_counters[] end else result = [] while true result << build_array[] return result if bump_counters[] end end end |
#put(index, item) ⇒ Vector #put(index) {|existing| ... } ⇒ Vector Also known as: set
Return a new ‘Vector` with a new value at the given `index`. If `index` is greater than the length of the vector, the returned vector will be padded with `nil`s to the correct size.
167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/hamster/vector.rb', line 167 def put(index, item = yield(get(index))) raise IndexError, "index #{index} outside of vector bounds" if index < -@size index += @size if index < 0 if index > @size suffix = Array.new(index - @size, nil) suffix << item replace_suffix(@size, suffix) else update_root(index, item) end end |
#rassoc(obj) ⇒ Object
Assumes all elements are nested, indexable collections, and searches through them, comparing ‘obj` with the second element of each nested collection. Return the first nested collection which matches, or `nil` if none is found. Behaviour is undefined when elements do not meet assumptions (i.e. are not indexable collections).
1263 1264 1265 1266 1267 1268 1269 |
# File 'lib/hamster/vector.rb', line 1263 def rassoc(obj) each do |array| next if !array.respond_to?(:[]) return array if obj == array[1] end nil end |
#repeated_combination(n) ⇒ self, Enumerator
When invoked with a block, yields all repeated combinations of length ‘n` of items from the `Vector`, and then returns `self`. A “repeated combination” is one in which any item from the `Vector` can appear consecutively any number of times.
There is no guarantee about which order the combinations will be yielded in.
If no block is given, an ‘Enumerator` is returned instead.
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 |
# File 'lib/hamster/vector.rb', line 890 def repeated_combination(n) return enum_for(:repeated_combination, n) if not block_given? if n < 0 # yield nothing elsif n == 0 yield [] elsif n == 1 each { |item| yield [item] } elsif @size == 0 # yield nothing else combos = lambda do |result,index,remaining| while index < @size-1 if remaining == 1 yield result.dup << get(index) else combos[result.dup << get(index), index, remaining-1] end index += 1 end item = get(index) remaining.times { result << item } yield result end combos[[], 0, n] end self end |
#repeated_permutation(n = @size) ⇒ self, Enumerator
When invoked with a block, yields all repeated permutations of length ‘n` of items from the `Vector`, and then returns `self`. A “repeated permutation” is one where any item from the `Vector` can appear any number of times, and in any position (not just consecutively)
If no length ‘n` is specified, permutations of all elements will be yielded. There is no guarantee about which order the permutations will be yielded in.
If no block is given, an ‘Enumerator` is returned instead.
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 |
# File 'lib/hamster/vector.rb', line 995 def repeated_permutation(n = @size) return enum_for(:repeated_permutation, n) if not block_given? if n < 0 # yield nothing elsif n == 0 yield [] elsif n == 1 each { |item| yield [item] } else result = [] perms = lambda do |index| 0.upto(@size-1) do |i| result[index] = get(i) if index < n-1 perms[index+1] else yield result.dup end end end perms[0] end self end |
#reverse ⇒ Vector
Return a new ‘Vector` with the same elements as this one, but in reverse order.
552 553 554 |
# File 'lib/hamster/vector.rb', line 552 def reverse self.class.new(((array = to_a).frozen? ? array.reverse : array.reverse!).freeze) end |
#reverse_each(&block) ⇒ self
Call the given block once for each item in the vector, from last to first.
446 447 448 449 450 |
# File 'lib/hamster/vector.rb', line 446 def reverse_each(&block) return enum_for(:reverse_each) unless block_given? reverse_traverse_depth_first(@root, @levels, &block) self end |
#rindex(obj) ⇒ Integer #rindex {|element| ... } ⇒ Integer
Find the index of an element, starting from the end of the vector. Returns ‘nil` if no element is found.
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 |
# File 'lib/hamster/vector.rb', line 1216 def rindex(obj = (missing_arg = true)) i = @size - 1 if missing_arg if block_given? reverse_each { |item| return i if yield item; i -= 1 } nil else enum_for(:rindex) end else reverse_each { |item| return i if item == obj; i -= 1 } nil end end |
#rotate(count = 1) ⇒ Vector
Return a new ‘Vector` with the same elements, but rotated so that the one at index `count` is the first element of the new vector. If `count` is positive, the elements will be shifted left, and those shifted past the lowest position will be moved to the end. If `count` is negative, the elements will be shifted right, and those shifted past the last position will be moved to the beginning.
569 570 571 572 |
# File 'lib/hamster/vector.rb', line 569 def rotate(count = 1) return self if (count % @size) == 0 self.class.new(((array = to_a).frozen? ? array.rotate(count) : array.rotate!(count)).freeze) end |
#sample ⇒ Object
Return a randomly chosen item from this ‘Vector`. If the vector is empty, return `nil`.
1178 1179 1180 |
# File 'lib/hamster/vector.rb', line 1178 def sample get(rand(@size)) end |
#select {|element| ... } ⇒ Vector Also known as: find_all, keep_if
Return a new ‘Vector` containing all elements for which the given block returns true.
461 462 463 464 |
# File 'lib/hamster/vector.rb', line 461 def select return enum_for(:select) unless block_given? reduce(self.class.empty) { |vector, item| yield(item) ? vector.add(item) : vector } end |
#shift ⇒ Vector
Return a new ‘Vector` with the first element removed. If empty, return `self`.
412 413 414 |
# File 'lib/hamster/vector.rb', line 412 def shift delete_at(0) end |
#shuffle ⇒ Vector
Return a new ‘Vector` with the same elements as this one, but randomly permuted.
515 516 517 |
# File 'lib/hamster/vector.rb', line 515 def shuffle self.class.new(((array = to_a).frozen? ? array.shuffle : array.shuffle!).freeze) end |
#vector.slice(index) ⇒ Object #vector.slice(index, length) ⇒ Vector #vector.slice(index..end) ⇒ Vector Also known as: []
Return specific objects from the ‘Vector`. All overloads return `nil` if the starting index is out of range.
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/hamster/vector.rb', line 312 def slice(arg, length = (missing_length = true)) if missing_length if arg.is_a?(Range) from, to = arg.begin, arg.end from += @size if from < 0 to += @size if to < 0 to += 1 if !arg.exclude_end? length = to - from length = 0 if length < 0 subsequence(from, length) else get(arg) end else arg += @size if arg < 0 subsequence(arg, length) end end |
#sort ⇒ Vector #sort {|a, b| ... } ⇒ Vector
Return a new ‘Vector` with the same items, but sorted.
672 673 674 |
# File 'lib/hamster/vector.rb', line 672 def sort self.class.new(super) end |
#sort_by {|element| ... } ⇒ Vector
Return a new ‘Vector` with the same items, but sorted. The sort order is determined by mapping the items through the given block to obtain sort keys, and then sorting the keys according to their natural sort order (`#<=>`).
688 689 690 |
# File 'lib/hamster/vector.rb', line 688 def sort_by self.class.new(super) end |
#take(n) ⇒ Vector
Return only the first ‘n` elements in a new `Vector`.
716 717 718 719 |
# File 'lib/hamster/vector.rb', line 716 def take(n) return self if n >= @size self.class.new(super) end |
#take_while ⇒ Vector, Enumerator
Gather elements up to, but not including, the first element for which the block returns ‘nil` or `false`, and return them in a new `Vector`. If no block is given, an `Enumerator` is returned instead.
744 745 746 747 |
# File 'lib/hamster/vector.rb', line 744 def take_while return enum_for(:take_while) if not block_given? self.class.new(super) end |
#to_a ⇒ Array Also known as: to_ary
Return an ‘Array` with the same elements, in the same order. The returned `Array` may or may not be frozen.
1275 1276 1277 1278 1279 1280 1281 1282 1283 |
# File 'lib/hamster/vector.rb', line 1275 def to_a if @levels == 0 # When initializing a Vector with 32 or less items, we always make # sure @root is frozen, so we can return it directly here @root else flatten_node(@root, @levels * BITS_PER_LEVEL, []) end end |
#transpose ⇒ Vector
Assume all elements are vectors or arrays and transpose the rows and columns. In other words, take the first element of each nested vector/array and gather them together into a new ‘Vector`. Do likewise for the second, third, and so on down to the end of each nested vector/array. Gather all the resulting `Vectors` into a new `Vector` and return it.
This operation is closely related to #zip. The result is almost the same as calling #zip on the first nested vector/array with the others supplied as arguments.
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 |
# File 'lib/hamster/vector.rb', line 1098 def transpose return self.class.empty if empty? result = Array.new(first.size) { [] } 0.upto(@size-1) do |i| source = get(i) if source.size != result.size raise IndexError, "element size differs (#{source.size} should be #{result.size})" end 0.upto(result.size-1) do |j| result[j].push(source[j]) end end result.map! { |a| self.class.new(a) } self.class.new(result) end |
#uniq(&block) ⇒ Vector
Return a new ‘Vector` with no duplicate elements, as determined by `#hash` and `#eql?`. For each group of equivalent elements, only the first will be retained.
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 |
# File 'lib/hamster/vector.rb', line 527 def uniq(&block) array = self.to_a if block_given? if array.frozen? self.class.new(array.uniq(&block).freeze) elsif array.uniq!(&block) # returns nil if no changes were made self.class.new(array.freeze) else self end elsif array.frozen? self.class.new(array.uniq.freeze) elsif array.uniq! # returns nil if no changes were made self.class.new(array.freeze) else self end end |
#unshift(object) ⇒ Vector
Return a new ‘Vector` with `object` inserted before the first element, moving the other elements upwards.
401 402 403 |
# File 'lib/hamster/vector.rb', line 401 def unshift(object) insert(0, object) end |
#values_at(*indices) ⇒ Vector
Return a new ‘Vector` with only the elements at the given `indices`, in the order specified by `indices`. If any of the `indices` do not exist, `nil`s will appear in their places.
1192 1193 1194 |
# File 'lib/hamster/vector.rb', line 1192 def values_at(*indices) self.class.new(indices.map { |i| get(i) }.freeze) end |
#zip(*others) ⇒ Vector #zip(*others) {|pair| ... } ⇒ nil
Combine two vectors by “zipping” them together. ‘others` should be arrays and/or vectors. The corresponding elements from this `Vector` and each of `others` (that is, the elements with the same indices) will be gathered into arrays.
If ‘others` contains fewer elements than this vector, `nil` will be used for padding.
643 644 645 646 647 648 649 |
# File 'lib/hamster/vector.rb', line 643 def zip(*others) if block_given? super else self.class.new(super) end end |