Class: Array

Inherits:
Object show all
Includes:
English::Array, Indexable, Random, Stackable
Defined in:
lib/gems/english-0.3.1/lib/english/array.rb,
lib/mack-facets/extensions/array.rb,
lib/gems/facets-2.4.5/lib/lore/facets/set.rb,
lib/gems/facets-2.4.5/lib/core/facets/blank.rb,
lib/gems/facets-2.4.5/lib/more/facets/tuple.rb,
lib/gems/facets-2.4.5/lib/more/facets/random.rb,
lib/gems/facets-2.4.5/lib/core/facets/boolean.rb,
lib/gems/facets-2.4.5/lib/core/facets/to_hash.rb,
lib/gems/facets-2.4.5/lib/more/facets/snapshot.rb,
lib/gems/facets-2.4.5/lib/more/facets/typecast.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/pad.rb,
lib/gems/facets-2.4.5/lib/more/facets/iteration.rb,
lib/gems/facets-2.4.5/lib/more/facets/syncarray.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/only.rb,
lib/gems/facets-2.4.5/lib/lore/facets/shellwords.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/index.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/merge.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/delete.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/rotate.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/select.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/splice.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/conjoin.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/product.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/product.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/traverse.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/indexable.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/not_empty.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/stackable.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/combination.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/permutation.rb,
lib/gems/facets-2.4.5/lib/core/facets/array/recursively.rb

Overview

SyncArray

A thread-safe array. We use a sync object instead of a mutex, because it is re-entrant. An exclusive lock is needed when writing, a shared lock IS NEEDED when reading.

Direct Known Subclasses

Autoarray, PathList, Pool, SyncArray

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Stackable

#peek, #pop, #push

Methods included from Indexable

#body, #ends, #first, #first=, #foot, #head, #last, #last=, #mid, #middle, #pos, #range, #tail, #thru

Methods included from Random

append_features

Methods included from English::Array

#conjunction

Class Method Details

.cast_from(object) ⇒ Object



191
192
193
194
195
196
# File 'lib/gems/facets-2.4.5/lib/more/facets/typecast.rb', line 191

def self.cast_from(object)
  return super
rescue TypeCastException
  return object.to_a if object.respond_to? :to_a
  raise
end

.mutable_methodsObject



34
35
36
37
38
39
40
# File 'lib/gems/facets-2.4.5/lib/more/facets/syncarray.rb', line 34

def self.mutable_methods
  @mutable ||= %w{ << []= abbrev clear collect! compact! concat
    delete delete_at delete_if fill flatten insert map! pop push
    reject! replace reverse! shift slice! sort! transpose uniq!
    unshift
  }
end

Instance Method Details

#_facets_indexObject



5
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/index.rb', line 5

alias_method :_facets_index, :index

#combination(k = 2) ⇒ Object

Yields the block to each unique combination of n elements.

a = %w|a b c d|
a.combination(3)

produces

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

CREDIT: Florian Gross



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/combination.rb', line 21

def combination(k=2)
  if block_given?
    s = 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
  else
    to_enum(:combination, k)
  end
end

#conjoin(*args, &block) ⇒ Object

This is more advnaced form of #join. It allows for fine control of separators.

NOTE: The old version used to default it’s separator to “, ” and default the terminating separator to “ and ”. This is no longer the case. You must specifically provide these parameters.

 [1,2,3].conjoin
 => "123"

 [1,2,3].conjoin(', ', ' and ')
 => "1, 2 and 3

 [1,2,3].conjoin(', ', :last => ' or ')
 => "1, 2 or 3

 [1,2,3].conjoin('; ', -1 => ' & ')
 => "1; 2 & 3

 [1,2,3,4].conjoin{ |i, a, b| i % 2 == 0 ? '.' : '-' }
 => "1.2-3.4"

 [1,1,2,2].conjoin{ |i, a, b| a == b ? '=' : '!=' }
 => "1=1!=2=2"

CREDIT: Trans


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/conjoin.rb', line 30

def conjoin(*args, &block)
  return first.to_s if size < 2

  sep = []

  if block_given?
    (size - 1).times do |i|
      sep << yield(i, *slice(i,2))
    end
  else
    options   = (Hash===args.last) ? args.pop : {}
    separator = args.shift || ""
    options[-1] = args.shift unless args.empty?

    sep = [separator] * (size - 1)

    if options.key?(:last)
      options[-1] = options.delete(:last)
    end

    options[-1] ||= " and "

    options.each{|i, s| sep[i] = s}
  end
  zip(sep).join
end

#countObject

This will give you a count, as a Hash, of all the values in the Array. %wspam eggs ham eggs spam.count # => => 2, “ham” => 1, “spam” => 3



91
92
93
94
95
# File 'lib/mack-facets/extensions/array.rb', line 91

def count
  k = Hash.new(0)
  self.each{|x| k[x] += 1}
  k
end

#delete_unless(&block) ⇒ Object

Inverse of #delete_if.

 [1,2,3].delete_unless{ |x| x < 2 }
 => [1,2]

CREDIT: Daniel Schierbeck


10
11
12
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/delete.rb', line 10

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]

CREDIT: Trans



22
23
24
25
26
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/delete.rb', line 22

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]

NOTE: It would be nice to see #delete_at incorporate this funcitonaility.

CREDIT: Trans


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/delete.rb', line 43

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_iterationObject

Iterate over each element of array using an iteration object.

[1,2,3].each_iteration do |it|
  p it.index
  p it.value
  p it.first?
  p it.last?
  p it.prior
  p it.after
end

on each successive iteration produces:

 0          1          2
 1          2          3
 true       false      false
 false      false      true
 []         [1]        [1,2]
 [2,3]      [3]        []

CREDIT: Trans


53
54
55
56
57
58
59
60
61
62
63
# File 'lib/gems/facets-2.4.5/lib/more/facets/iteration.rb', line 53

def each_iteration
  if block_given?
    it = It.new(self)
    each do |e|
      yield(it)
      it.send(:next_iteration)
    end
  else
    return Enumerable::Enumerator.new(self, :each_iteration)
  end
end

#include?(pat) ⇒ Boolean

Returns:

  • (Boolean)


7
8
9
10
11
12
13
14
15
16
# File 'lib/mack-facets/extensions/array.rb', line 7

def include?(pat)
  if pat.is_a?(Regexp)
    self.each do |v|
      return true if v.to_s.match(pat)
    end
    return false
  else
    return _original_include?(pat)
  end
end

#index(obj = nil, &block) ⇒ Object

Allows #index to accept a block.

OVERRIDE! This is one of the bery few core overrides in Facets.



12
13
14
15
16
17
18
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/index.rb', line 12

def index(obj=nil, &block)
  if block_given?
    _facets_index(find(&block))
  else
    _facets_index(obj)
  end
end

#invertObject

This will invert the index and the values and return a Hash of the results. %wyellow orange.invert # => => 0, “orange” => 2, “yellow” => 1



99
100
101
102
103
# File 'lib/mack-facets/extensions/array.rb', line 99

def invert
  h = {}
  self.each_with_index{|x,i| h[x] = i}
  h
end

#merge!(other) ⇒ Object

In place #merge.

 a = [1,2]
 a.merge! [2,3]
 a => [1,2,3]

CREDIT: Trans


11
12
13
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/merge.rb', line 11

def merge!( other )
  self.replace(self.merge(other))
end

#not_empty?Boolean

Not empty?

[].not_empty?     #=> false
[1,2].not_empty?  #=> true

Returns:

  • (Boolean)


8
9
10
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/not_empty.rb', line 8

def not_empty?
  !empty?
end

#onlyObject

Returns the only element in the array. Raises an IndexError if the array’s size is not 1.

 [5].only      # -> 5
 [1,2,3].only  # -> IndexError
 [].only       # -> IndexError

CREDIT: Gavin Sinclair
CREDIT: Noah Gibbs


13
14
15
16
17
18
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/only.rb', line 13

def only
  unless size == 1
    raise IndexError, "Array#only called on non-single-element array"
  end
  first
end

#pad(len, val = nil) ⇒ Object

Pad an array with a given value upto a given length.

[0,1,2].pad(6,"a")  #=> [0,1,2,"a","a","a"]

If length is a negative number padding will be added to the beginning of the array.

 [0,1,2].pad(-6,"a")  #=> ["a","a","a",0,1,2]

CREDIT: Richard Laugesen


14
15
16
17
18
19
20
21
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/pad.rb', line 14

def pad(len, val=nil)
  return dup if self.size >= len.abs
  if len < 0
    Array.new((len+size).abs,val) + self
  else
    self + Array.new(len-size,val)
  end
end

#pad!(len, val = nil) ⇒ Object

Like #pad but changes the array in place.

  a = [0,1,2]
  a.pad!(6,"x")
  a  #=> [0,1,2,"x","x","x"]

CREDIT: Richard Laugesen


31
32
33
34
35
36
37
38
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/pad.rb', line 31

def pad!(len, val=nil)
  return self if self.size >= len.abs
  if len < 0
    replace Array.new((len+size).abs,val) + self
  else
    concat Array.new(len-size,val)
  end
end

#parse_splat_argsObject

This method is useful when you have a method that looks like this: def foo(*args)

do something

end The problem is when you use the * like that everything that comes in is an array. Here are a few problems with this: foo([1,2,3]) When you pass an array into this type of method you get the following nested array:

[1,2,3]

The parse_splat_args method, if called, would do this: args.parse_splat_args # => [1,2,3] Now say you called this method like such: foo(1) args would be [1] args.parse_splat_args # => 1 Finally foo args.parse_splat_args # => nil



36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/mack-facets/extensions/array.rb', line 36

def parse_splat_args
  unless self.empty?
    args = self#.flatten
    case args.size
    when 1
      return args.first # if there was only one arg passed, return just that, without the array
    when 0
      return nil # if no args were passed return nil
    else
      return args # else return the array back, cause chances are that's what they passed you!
    end
  end
end

#permutation(n = size) ⇒ Object

Permutation provids the possible orders of an enumerable. Each is indexed by a permutation number. The maximum number of arrangements is the factorial of the size of the array.

CREDIT: Shin-ichiro Hara


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/permutation.rb', line 11

def permutation(n=size)
  if size < n or n < 0
  elsif n == 0
    yield([])
  else
    self[1..-1].permutation(n - 1) do |x|
      (0...n).each do |i|
        yield(x[0...i] + [first] + x[i..-1])
      end
    end
    self[1..-1].permutation(n) do |x|
      yield(x)
    end
  end
end

#pick_randomObject

This will pick a random value from the array



69
70
71
# File 'lib/mack-facets/extensions/array.rb', line 69

def pick_random
  self[rand(self.length)]
end

#power_setObject



16
17
18
19
20
21
22
23
24
25
# File 'lib/gems/facets-2.4.5/lib/lore/facets/set.rb', line 16

def power_set
  if empty?
    [self]
  else
    subset  = dup
    value   = [ subset.pop ]
    subsubs = subset.power_set
    subsubs.concat( subsubs.map{ |subset| subset + value } )
  end
end

#product(*enums, &block) ⇒ Object Also known as: **

Provides the cross-product of two or more Enumerables. This is the class-level method. The instance method calls on this.

 Enumerable.cartesian_product([1,2], [4], ["apple", "banana"])
 #=> [[1, 4, "apple"], [1, 4, "banana"], [2, 4, "apple"], [2, 4, "banana"]]

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

 a = []
 [1,2].cart([4,5]){|elem| a << elem }
 a  #=> [[1, 4],[1, 5],[2, 4],[2, 5]]

CREDIT: Thomas Hafner


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/product.rb', line 21

def product(*enums, &block)
  enums.unshift self
  result = [[]]
  while [] != enums
    t, result = result, []
    b, *enums = enums
    t.each do |a|
      b.each do |n|
        result << a + [n]
      end
    end
  end
  if block_given?
    result.each{ |e| block.call(e) }
  else
    result
  end
end

#random_eachObject

This allows you to easily recurse of the array randomly.



74
75
76
# File 'lib/mack-facets/extensions/array.rb', line 74

def random_each
  self.randomize.each {|x| yield x}
end

#randomize(&block) ⇒ Object

This will return a new instance of the array sorted randomly.



51
52
53
54
55
56
57
# File 'lib/mack-facets/extensions/array.rb', line 51

def randomize(&block)
  if block_given?
    self.sort {|x,y| yield x, y}
  else
    self.sort_by { rand }
  end
end

#randomize!(&block) ⇒ Object

This calls the randomize method, but will permantly replace the existing array.



60
61
62
63
64
65
66
# File 'lib/mack-facets/extensions/array.rb', line 60

def randomize!(&block)
  if block_given?
    self.replace(self.randomize(&block))
  else
    self.replace(self.randomize)
  end
end

#recursively {|a| ... } ⇒ Object

Apply a block to hash, and recursively apply that block to each subhash.

arr = ["a", ["b", "c", nil], nil]
arr.recursively{|a| a.compact! }
=> ["a", ["b", "c"]]

TODO: Can this be generalized in Enumerbale?

Yields:

  • (a)


12
13
14
15
16
17
18
19
20
21
22
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/recursively.rb', line 12

def recursively(&block)
  a = inject([]) do |array, value|
    if value.is_a?(Array)
      array << value.recursively(&block)
    else
      array << value
    end
    array
  end
  yield a
end

#recursively!(&block) ⇒ Object

In place form of #recursively.



26
27
28
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/recursively.rb', line 26

def recursively!(&block)
  replace(recursively(&block))
end

#restore_snapshot(snap) ⇒ Object



185
# File 'lib/gems/facets-2.4.5/lib/more/facets/snapshot.rb', line 185

def restore_snapshot(snap) replace(snap) 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]

CREDIT: Florian Gross
CREDIT: Thomas Sawyer


17
18
19
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/rotate.rb', line 17

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]

CREDIT: Florian Gross
CREDIT: Thomas Sawyer


30
31
32
33
34
35
36
37
38
39
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/rotate.rb', line 30

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]

CREDIT: Gavin Sinclair


11
12
13
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/select.rb', line 11

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

#splice(*args) ⇒ Object

Splice acts a combination of #slice! and #store. If two arguments are given it calls #store. If a single argument is give it calls slice!.

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

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

CREDIT: Trans


17
18
19
20
21
22
23
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/splice.rb', line 17

def splice(*args)
  if args.size == 1
    slice!(*args)
  else
    store(*args)
  end
end

#subset?(other) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
81
82
83
# File 'lib/mack-facets/extensions/array.rb', line 78

def subset?(other)
  self.each do |x|
    return false if !(other.include? x)
  end
  true
end

#superset?(other) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
# File 'lib/mack-facets/extensions/array.rb', line 85

def superset?(other)
  other.subset?(self)
end

#take_snapshotObject



184
# File 'lib/gems/facets-2.4.5/lib/more/facets/snapshot.rb', line 184

def take_snapshot() dup end

#to_bObject

Boolean conversion for not empty?



60
61
62
# File 'lib/gems/facets-2.4.5/lib/core/facets/boolean.rb', line 60

def to_b
  ! self.empty?
end

#to_h(arrayed = nil) ⇒ Object

Converts a two-element associative array into a hash.

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

If arrayed is set it will maintain trailing arrays.

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

Note that the use of a values parameter has been deprecated because that functionality is as simple as:

 array1.zip(array2).to_h

CREDIT: Trans


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/gems/facets-2.4.5/lib/core/facets/to_hash.rb', line 20

def to_h(arrayed=nil)
  h = {}
  if arrayed #or (flatten.size % 2 == 1)
    #each{ |e| h[e.first] = e.slice(1..-1) }
    each{ |k,*v| h[k] = v }
  else
    #h = Hash[*flatten(1)] # TODO Use in 1.9 instead.
    ary = []
    each do |a|
      Array===a ? ary.concat(a) : ary << a
    end
    h = Hash[*ary]
  end
  h
end

#to_shellObject Also known as: to_console



50
51
52
# File 'lib/gems/facets-2.4.5/lib/lore/facets/shellwords.rb', line 50

def to_shell
  to_shellwords.join(' ')
end

#to_shellwordsObject

Convert an array into command line parameters. The array is accepted in the format of Ruby method arguments –ie. [arg1, arg2, …, hash]



44
45
46
47
48
# File 'lib/gems/facets-2.4.5/lib/lore/facets/shellwords.rb', line 44

def to_shellwords
  flags = (Hash===last ? pop : {})
  flags = flags.to_shellwords
  flags + ' ' + self #join(" ")
end

#to_tObject



320
321
322
# File 'lib/gems/facets-2.4.5/lib/more/facets/tuple.rb', line 320

def to_t
  Tuple.cast_from_array( self )
end

#traverse(&block) ⇒ Object



5
6
7
8
9
10
11
12
13
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/traverse.rb', line 5

def traverse(&block)
  map do |item|
    if item.is_a?(self.class)
      item.traverse(&block)
    else
      yield item
    end
  end
end

#traverse!(&block) ⇒ Object



17
18
19
# File 'lib/gems/facets-2.4.5/lib/core/facets/array/traverse.rb', line 17

def traverse!(&block)
  replace(traverse(&block))
end