Class: Hamster::Vector
- Inherits:
-
Object
- Object
- Hamster::Vector
- Includes:
- Associable, Enumerable
- 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]
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. -
.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 withother
. -
#add(item) ⇒ Vector
(also: #<<, #push)
Return a new
Vector
withitem
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 theVector
, and then returnsself
. -
#delete(obj) ⇒ Vector
Return a new
Vector
with all items which are equal toobj
removed. -
#delete_at(index) ⇒ Vector
Return a new
Vector
with the element atindex
removed. -
#drop(n) ⇒ Vector
Drop the first
n
elements and return the rest in a newVector
. -
#drop_while ⇒ Vector, Enumerator
Drop elements up to, but not including, the first element for which the block returns
nil
orfalse
. -
#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 thisVector
contains no items. -
#eql?(other) ⇒ Boolean
Return true if
other
has the same type and contents as thisVector
. -
#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 thisVector
. -
#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 atindex
. -
#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. -
#permutation(n = @size) ⇒ self, Enumerator
Yields all permutations of length
n
of items from theVector
, and then returnsself
. -
#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 givenindex
. -
#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 theVector
, and then returnsself
. -
#repeated_permutation(n = @size) ⇒ self, Enumerator
When invoked with a block, yields all repeated permutations of length
n
of items from theVector
, and then returnsself
. -
#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 indexcount
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 newVector
. -
#take_while ⇒ Vector, Enumerator
Gather elements up to, but not including, the first element for which the block returns
nil
orfalse
, and return them in a newVector
. -
#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
withobject
inserted before the first element, moving the other elements upwards. -
#values_at(*indices) ⇒ Vector
Return a new
Vector
with only the elements at the givenindices
, in the order specified byindices
. -
#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, #reject, #sum, #to_set
Methods included from Enumerable
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 |
.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.
746 747 748 749 750 751 |
# File 'lib/hamster/vector.rb', line 746 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
.
599 600 601 602 603 |
# File 'lib/hamster/vector.rb', line 599 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).
1238 1239 1240 1241 1242 1243 1244 |
# File 'lib/hamster/vector.rb', line 1238 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.
1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 |
# File 'lib/hamster/vector.rb', line 1132 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.
1163 1164 1165 |
# File 'lib/hamster/vector.rb', line 1163 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.
825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 |
# File 'lib/hamster/vector.rb', line 825 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
.
689 690 691 692 693 694 |
# File 'lib/hamster/vector.rb', line 689 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.
718 719 720 721 |
# File 'lib/hamster/vector.rb', line 718 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
.
1285 1286 1287 1288 1289 |
# File 'lib/hamster/vector.rb', line 1285 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.
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 |
# File 'lib/hamster/vector.rb', line 790 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
.
578 579 580 581 582 583 584 585 586 587 588 |
# File 'lib/hamster/vector.rb', line 578 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
.
1293 1294 1295 |
# File 'lib/hamster/vector.rb', line 1293 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 |
#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.
928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 |
# File 'lib/hamster/vector.rb', line 928 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.
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 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 |
# File 'lib/hamster/vector.rb', line 1026 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).
1258 1259 1260 1261 1262 1263 1264 |
# File 'lib/hamster/vector.rb', line 1258 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.
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 |
# File 'lib/hamster/vector.rb', line 878 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.
983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 |
# File 'lib/hamster/vector.rb', line 983 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.
540 541 542 |
# File 'lib/hamster/vector.rb', line 540 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.
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 |
# File 'lib/hamster/vector.rb', line 1211 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.
557 558 559 560 |
# File 'lib/hamster/vector.rb', line 557 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
.
1173 1174 1175 |
# File 'lib/hamster/vector.rb', line 1173 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.
660 661 662 |
# File 'lib/hamster/vector.rb', line 660 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
(#<=>
).
676 677 678 |
# File 'lib/hamster/vector.rb', line 676 def sort_by self.class.new(super) end |
#take(n) ⇒ Vector
Return only the first n
elements in a new Vector
.
704 705 706 707 |
# File 'lib/hamster/vector.rb', line 704 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.
732 733 734 735 |
# File 'lib/hamster/vector.rb', line 732 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.
1270 1271 1272 1273 1274 1275 1276 1277 1278 |
# File 'lib/hamster/vector.rb', line 1270 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.
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 |
# File 'lib/hamster/vector.rb', line 1086 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) rescue NoMethodError if any? { |x| !x.respond_to?(:size) || !x.respond_to?(:[]) } bad = find { |x| !x.respond_to?(:size) || !x.respond_to?(:[]) } raise TypeError, "'#{bad.inspect}' must respond to #size and #[] to be transposed" else raise end 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 |
# File 'lib/hamster/vector.rb', line 527 def uniq(&block) array = self.to_a return self.class.new(array.uniq(&block).freeze) if array.frozen? return self.class.new(array.freeze) if array.uniq!(&block) self 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.
1187 1188 1189 |
# File 'lib/hamster/vector.rb', line 1187 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.
631 632 633 634 635 636 637 |
# File 'lib/hamster/vector.rb', line 631 def zip(*others) if block_given? super else self.class.new(super) end end |