Class: Array

Inherits:
Object show all
Defined in:
lib/nano/array/delete_unless.rb,
lib/nano/array/mid.rb,
lib/nano/array/pos.rb,
lib/nano/array/bulk.rb,
lib/nano/array/foot.rb,
lib/nano/array/head.rb,
lib/nano/array/pick.rb,
lib/nano/array/slap.rb,
lib/nano/array/tail.rb,
lib/nano/array/thru.rb,
lib/nano/array/to_b.rb,
lib/nano/array/to_h.rb,
lib/nano/array/range.rb,
lib/nano/array/store.rb,
lib/nano/array/%5B%5D.rb,
lib/nano/array/middle.rb,
lib/nano/array/rotate.rb,
lib/nano/array/at_rand.rb,
lib/nano/array/last%21.rb,
lib/nano/array/last%3D.rb,
lib/nano/array/pick%21.rb,
lib/nano/array/shuffle.rb,
lib/nano/array/first%21.rb,
lib/nano/array/first%3D.rb,
lib/nano/array/%5B%5D%3D.rb,
lib/nano/array/rotate%21.rb,
lib/nano/array/select%21.rb,
lib/nano/array/at_rand%21.rb,
lib/nano/array/last_index.rb,
lib/nano/array/rand_index.rb,
lib/nano/array/shuffle%21.rb,
lib/nano/array/rand_subset.rb,
lib/nano/enumerable/each_by.rb,
lib/nano/array/delete_values.rb,
lib/nano/enumerable/each_slice.rb,
lib/nano/array/delete_values_at.rb,
lib/nano/enumerable/each_combination.rb,
lib/nano/enumerable/each_permutation.rb,
lib/nano/enumerable/each_unique_pair.rb

Overview

Daniel Schierbeck

Instance Method Summary collapse

Instance Method Details

#[](*args) ⇒ Object

Modifies #[] to also accept an array of indexes.

a = ['a','b','c','d','e','f']

a[[1]]      #=> ['b']
a[[1,1]]    #=> ['b','b']
a[[1,-1]]   #=> ['b','f']
a[[0,2,4]]  #=> ['a','c','e']


13
14
15
16
# File 'lib/nano/array/%5B%5D.rb', line 13

def [](*args)
  return values_at(*args.at(0)) if Array === args.at(0)
  return slice(*args)
end

#[]=(*args) ⇒ Object

Modifies #[]= to accept an array of indexes for assignment.

a = ['a','b','c','d']

a[[1,-1]] = ['m','n']    #=> ['m','n']
a                        #=> ['a','m','c','n']


12
13
14
15
16
17
18
19
20
# File 'lib/nano/array/%5B%5D%3D.rb', line 12

def []=(*args)
  if Array === args.at(0)
    idx,vals = args.at(0),args.at(1)
    idx.each_with_index{ |a,i| store(a,vals.at(i)) }
    return values_at( *idx )
  else
    return store(*args)
  end
end

#at_randObject

Return a random element of the array.

[1, 2, 3, 4].at_rand           #=> 2
[1, 2, 3, 4].at_rand           #=> 4


7
8
9
# File 'lib/nano/array/at_rand.rb', line 7

def at_rand
  self.at( rand( size ) )
end

#at_rand!Object

Same as #at_rand, but acts in place removing a random element from the array.

a = [1,2,3,4]
a.at_rand!       #=> 2
a                #=> [1,3,4]


9
10
11
# File 'lib/nano/array/at_rand%21.rb', line 9

def at_rand!
  return delete_at( Kernel.rand( size ) )
end

#bulkObject

Returns an array of the first element upto, but not including, the last element.

[1,2,3].bulk  #=> [1,2]


7
8
9
# File 'lib/nano/array/bulk.rb', line 7

def bulk
  slice(0,length-1)
end

#delete_unless(&block) ⇒ Object



3
4
5
# File 'lib/nano/array/delete_unless.rb', line 3

def delete_unless (&block)
  delete_if { |element| not block.call(element) }
end

#delete_values(*values) ⇒ Object

Delete multiple values from array.

a = [1,2,3,4]
a.delete_values(1,2)   #=> [1,2]
a                      #=> [3,4]


9
10
11
12
13
# File 'lib/nano/array/delete_values.rb', line 9

def delete_values(*values)
  d = []
  values.each{ |v| d << delete(v) }
  d
end

#delete_values_at(*selectors) ⇒ Object

Delete multiple values from array given indexes or index range.

a = [1,2,3,4]
a.delete_values_at(1,2)   #=> [2,3]
a                         #=> [1,4]
a = [1,2,3,4]
a.delete_values_at(0..2)  #=> [1,2,3]
a                         #=> [4]


14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/nano/array/delete_values_at.rb', line 14

def delete_values_at(*selectors)
  idx = []
  selectors.each{ |i|
    case i
    when Range
      idx.concat( i.to_a )
    else
      idx << i.to_i
    end
  }
  idx.uniq!
  dvals = values_at(*idx)
  idx = (0...size).to_a - idx
  self.replace( values_at(*idx) )
  return dvals
end

#each_byObject



8
# File 'lib/nano/enumerable/each_by.rb', line 8

alias_method( :each_by, :each_slice )

#each_combination(k = 2) ⇒ Object

Yields the block to each unique combination of n elements.

a = %w|a b c d|
a.each_combination(3) do |c|
  p c
end

produces

["a", "b", "c"]
["a", "b", "d"]
["a", "c", "d"]
["b", "c", "d"]


18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/nano/enumerable/each_combination.rb', line 18

def each_combination(k=2)
  s = self.to_a
  n = s.size
  return unless (1..n) === k
  idx = (0...k).to_a
  loop do
    yield s.values_at(*idx)
    i = k - 1
    i -= 1 while idx[i] == n - k + i
    break if i < 0
    idx[i] += 1
    (i + 1 ... k).each {|j| idx[j] = idx[i] + j - i}
  end
end

#each_permutation(prefixed = []) ⇒ Object

Applys a block to each possible permutation of an array.

%w[a b c].each_permutation { |x| puts(x.join('')) }

produces

abc
acb
bac
bca
cab
cba

– Credit goes to Paul Battley. ++



20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/nano/enumerable/each_permutation.rb', line 20

def each_permutation( prefixed=[] )
  s = self.to_a
  if (length < 2)
    # there are no elements left to permute
    yield(prefixed + self)
  else
    # recursively permute the remaining elements
    s.each_with_index do |e, i|
      (s[0,i]+s[(i+1)..-1]).permute(prefixed+[e]) { |a| yield a }
    end
  end
end

#each_slice(n = nil, &yld) ⇒ Object

Iterates over n elements at a time. If n is not given then the arity of the block determines the slicing quantity.

[1, 2, 3, 4].each_slice(2){ |a,b| ... }

This is a specialized version Enumerable#each_slice but optimized specifically for Array.



48
49
50
51
52
53
54
55
# File 'lib/nano/enumerable/each_slice.rb', line 48

def each_slice(n=nil, &yld)
  n = yld.arity.abs unless n
  i=0
  while i < self.length
    yld.call(*self.slice(i,n))
    i+=n
  end
end

#each_unique_pair(&yld) ⇒ Object

Processes each unique pair (of indices, not value) in the array by yielding them to the supplied block.

a = [1,2,3,4]
a.each_unique_pair{ |a,b| puts a+','+b }

produces

1,2
1,3
1,4
2,3
2,4
3,4

This does not guarantee the uniqueness of values. For example:

a = [1,2,1]
a.each_unique_pair{ |a,b| puts a+','+b }

prduces

1,2
1,1
2,1

This is equivalent to each_combination(2){ ... }.



33
34
35
36
37
38
39
# File 'lib/nano/enumerable/each_unique_pair.rb', line 33

def each_unique_pair(&yld)
  self.each_combination(2,&yld)
  #s = self.to_a
  #self.each_with_index{ |a,i|
  #  self[(i+1)..-1].each{ |b| yield a,b }
  #}
end

#first=(x) ⇒ Object

Change the first element.

a = ["a","y","z"]
a.first = "x"
p a           #=> ["x","y","z"]


10
11
12
# File 'lib/nano/array/first%3D.rb', line 10

def first=(x)
  self[0] = x
end

#footObject

Like #last, returning the last element in an array.

[1,2,3].foot  #=> [3]


8
9
10
# File 'lib/nano/array/foot.rb', line 8

def foot
  slice(-1,1)
end

#headObject

Like #first but returns the first element in a new array.

[1,2,3].head  #=> [1]


7
8
9
# File 'lib/nano/array/head.rb', line 7

def head
  slice(0,1)
end

#last=(x) ⇒ Object

Change the last element.

a = [1,2,5]
a.last = 3
p a           #=> [1,2,3]


9
10
11
# File 'lib/nano/array/last%3D.rb', line 9

def last=(x)
  self[-1] = x
end

#last_indexObject

Returns the last index of the array. Returns nil is array has no elements.

[1,2,3,4,5].last_index  #=> 4


7
8
9
10
# File 'lib/nano/array/last_index.rb', line 7

def last_index
  return nil if self.length == 0
  self.length - 1
end

#mid(offset = 0) ⇒ Object

Returns the middle element of an array, or the element offset from middle if the parameter is given. Even-sized arrays, not having an exact middle, return the middle-right element.

[1,2,3,4,5].mid        #=> 3
[1,2,3,4,5,6].mid      #=> 4
[1,2,3,4,5,6].mid(-1)  #=> 3
[1,2,3,4,5,6].mid(-2)  #=> 2
[1,2,3,4,5,6].mid(1)   #=> 5

In other words, If there are an even number of elements the higher-indexed of the two center elements is indexed as orgin (0).



15
16
17
# File 'lib/nano/array/mid.rb', line 15

def mid(offset=0)
  self.at( (self.length / 2) + offset )
end

#middleObject

Returns the middle element(s) of an array. Even-sized arrays, not having an exact middle, returns a two-element array of the two middle elements.

[1,2,3,4,5].mid        #=> 3
[1,2,3,4,5,6].mid      #=> [3,4]

In contrast to #mid which utilizes an offset.



10
11
12
13
14
15
16
# File 'lib/nano/array/middle.rb', line 10

def middle
  if size % 2 == 0
    [ at((size/2)-1), at(size/2) ]
  else
    at(size/2)
  end
end

#pick(n = nil) ⇒ Object

Similar to #at_rand, but will return an array of randomly picked exclusive elements if given a number.



7
8
9
10
11
12
13
14
# File 'lib/nano/array/pick.rb', line 7

def pick(n=nil)
  if n
    a = self.dup
    a.pick!(n)
  else
    at( Kernel.rand( size ) )
  end
end

#pick!(n = nil) ⇒ Object

Similar to #at_rand!, but given a number will return an array of exclusive elements.



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/nano/array/pick%21.rb', line 7

def pick!(n=nil)
  if n
    if n > self.size
      r = self.dup
      self.replace([])
      r
    else
      r = []
      n.times { r << delete_at( Kernel.rand( size ) ) }
      r
    end
  else
    delete_at( Kernel.rand( size ) )
  end
end

#pos(i) ⇒ Object

Returns the positive ordinal index given a cardinal position, 1 to n or -n to -1.

[1,2,3,4,5].pos(1)   #=> 0
[1,2,3,4,5].pos(-1)  #=> 4


8
9
10
11
12
13
14
# File 'lib/nano/array/pos.rb', line 8

def pos(i)
  if i > 0
    return i - 1
  else
    self.length + i
  end
end

#rand_indexObject



2
3
4
# File 'lib/nano/array/rand_index.rb', line 2

def rand_index
  rand( size )
end

#rand_subset(number = nil, exclusive = true) ⇒ Object

Returns a random subset of an Array. If a number of elements is specified then returns that number of elements, otherwise returns a random number of elements upto the size of the Array.

By defualt the returned values are exclusive of each other, but if exclusive is set to false, the same values can be choosen more than once.

When exclusive is true (the default) and the number given is greater than the size of the array, then all values are returned.

[1, 2, 3, 4].rand_subset(1)        #=> [2]
[1, 2, 3, 4].rand_subset(4)        #=> [2, 1, 3, 4]
[1, 2, 3, 4].rand_subset           #=> [1, 3, 4]
[1, 2, 3, 4].rand_subset           #=> [2, 3]


22
23
24
25
26
27
28
29
# File 'lib/nano/array/rand_subset.rb', line 22

def rand_subset( number=nil, exclusive=true )
  number = rand( size ) unless number
  number = number.to_int
  #return self.dup if (number >= size and exlusive)
  return sort_by{rand}.slice(0,number) if exclusive
  ri =[]; number.times { |n| ri << rand( size ) }
  return values_at(*ri)
end

#range(a = nil, z = nil) ⇒ Object

Returns the index range between two elements. If no elements are given, returns the range from first to last.

['a','b','c','d'].range            #=> 0..3
['a','b','c','d'].range('b','d')   #=> 1..2

– This could surely use a little error catch code (todo). ++



12
13
14
15
16
17
18
# File 'lib/nano/array/range.rb', line 12

def range(a=nil,z=nil)
  if !a
    0..self.length-1
  else
    index(a)..index(z)
  end
end

#rotate(n = 1) ⇒ Object

Rotates an array’s elements from back to front n times.

[1,2,3].rotate      #=> [3,1,2]
[3,1,2].rotate      #=> [2,3,1]
[3,1,2].rotate      #=> [1,2,3]
[1,2,3].rotate(3)   #=> [1,2,3]

A negative parameter reverses the order from front to back.

[1,2,3].rotate(-1)  #=> [2,3,1]


16
17
18
# File 'lib/nano/array/rotate.rb', line 16

def rotate(n=1)
  self.dup.rotate!(n)
end

#rotate!(n = 1) ⇒ Object

Same as #rotate, but acts in place.

a = [1,2,3]
a.rotate!
a  #=> [3,1,2]


8
9
10
11
12
13
14
15
16
17
# File 'lib/nano/array/rotate%21.rb', line 8

def rotate!(n=1)
  n = n.to_int
  return self if (n == 0 or self.empty?)
  if n > 0
    n.abs.times{ self.unshift( self.pop ) }
  else
    n.abs.times{ self.push( self.shift ) }
  end
  self
end

#select!Object

As with #select but modifies the Array in place.

a = [1,2,3,4,5,6,7,8,9,10]
a.select!{ |e| e % 2 == 0 }
a  #=> [2,4,6,8,10]


8
9
10
# File 'lib/nano/array/select%21.rb', line 8

def select!  # :yield:
  reject!{ |e| not yield(e) }
end

#shuffleObject

Randomize the order of an array.

[1,2,3,4].shuffle  #=> [2,4,1,3]


12
13
14
15
# File 'lib/nano/array/shuffle.rb', line 12

def shuffle
  dup.shuffle!
  #sort_by{Kernel.rand}
end

#shuffle!Object

As with #shuffle but modifies the array in place. The algorithm used here is known as a Fisher-Yates shuffle.

a = [1,2,3,4]
a.shuffle!
a  #=> [2,4,1,3]


14
15
16
17
18
19
20
21
22
23
24
# File 'lib/nano/array/shuffle%21.rb', line 14

def shuffle!
  s = size
  each_index do |j|
    i = Kernel.rand(s-j)
    #self[j], self[j+i] = self[j+i], self[j]
    tmp = self[j]
    self[j] = self[j+i]
    self[j+i] = tmp
  end
  self
end

#storeObject

Alias for #[]=.



3
# File 'lib/nano/array/store.rb', line 3

alias_method( :store, :[]= )

#tailObject

Returns an array from second element to last element.

[1,2,3].tail  #=> [2,3]


6
7
8
# File 'lib/nano/array/tail.rb', line 6

def tail
  slice(1,length-1)
end

#thru(from, to) ⇒ Object

Fetch values from a start index thru an end index.

[1,2,3,4,5].thru(0,2)  #=> [1,2,3]
[1,2,3,4,5].thru(2,4)  #=> [3,4,5]


7
8
9
10
11
12
13
14
15
# File 'lib/nano/array/thru.rb', line 7

def thru( from, to )
  a = []
  i = from
  while i <= to
    a << self.at(i)
    i += 1
  end
  a
end

#to_bObject

Boolean conversion for not empty?



3
4
5
# File 'lib/nano/array/to_b.rb', line 3

def to_b
  ! self.empty?
end

#to_h(values = nil) ⇒ Object

Produces a hash for an Array, or two arrays.

If no parameter is given, to_h expects the receiving array to be associative.

a1 = [ [:a,1], [:b,2] ]
a1.to_h  #=> { :a=>1, :b=>2 }

If an array is given it is considered values and zipped with the receiver, to produce the hash.

a1 = [ :a, :b ]
a2 = [ 1, 2 ]
a1.to_h(a2)  #=> { :a=>1, :b=>2 }


18
19
20
21
22
23
24
25
26
# File 'lib/nano/array/to_h.rb', line 18

def to_h(values=nil)
  h = {}
  if values
    keys.size.times{ |i| h[at(i)] = values.at(i) }
  else
    each{ |e| h[e.first] = e.slice(1..-1) }
  end
  return h
end