Class: Array

Inherits:
Object show all
Includes:
Indexable, Random::ArrayExtensions
Defined in:
lib/standard/facets/pathname/to_path.rb,
lib/core/facets/boolean.rb,
lib/core/facets/array/zip.rb,
lib/core/facets/array/pad.rb,
lib/core/facets/array/mode.rb,
lib/core/facets/array/pull.rb,
lib/core/facets/array/step.rb,
lib/core/facets/array/to_h.rb,
lib/core/facets/array/only.rb,
lib/core/facets/array/from.rb,
lib/core/facets/array/store.rb,
lib/core/facets/array/merge.rb,
lib/core/facets/array/occur.rb,
lib/core/facets/array/split.rb,
lib/core/facets/array/before.rb,
lib/core/facets/array/divide.rb,
lib/core/facets/array/splice.rb,
lib/core/facets/array/median.rb,
lib/core/facets/kernel/blank.rb,
lib/core/facets/array/op_pow.rb,
lib/core/facets/array/recurse.rb,
lib/core/facets/array/nonuniq.rb,
lib/core/facets/array/uniq_by.rb,
lib/core/facets/array/entropy.rb,
lib/core/facets/array/missing.rb,
lib/core/facets/array/conjoin.rb,
lib/core/facets/array/squeeze.rb,
lib/core/facets/array/arrange.rb,
lib/core/facets/array/contains.rb,
lib/core/facets/array/collapse.rb,
lib/core/facets/array/traverse.rb,
lib/core/facets/array/indexable.rb,
lib/core/facets/array/each_pair.rb,
lib/core/facets/array/not_empty.rb,
lib/core/facets/array/duplicates.rb,
lib/core/facets/array/each_value.rb,
lib/core/facets/array/occurrence.rb,
lib/core/facets/array/commonality.rb,
lib/core/facets/array/recursively.rb,
lib/core/facets/array/probability.rb,
lib/core/facets/array/intersection.rb,
lib/core/facets/array/each_overlap.rb,
lib/core/facets/object/object_state.rb,
lib/core/facets/array/delete_values.rb,
lib/core/facets/array/reject_values.rb,
lib/core/facets/array/delete_unless.rb,
lib/core/facets/array/extract_options.rb,
lib/core/facets/array/unique_permutation.rb,
lib/standard/facets/set.rb,
lib/standard/facets/tuple.rb,
lib/standard/facets/random.rb,
lib/standard/facets/shellwords.rb

Overview

class NilClass

# Provide platform dependent null path.
#
# @standard
#   require 'facets/pathname'
#
# @author Daniel Burger
def to_path
  Pathname.null
end

end

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Random::ArrayExtensions

#at_rand, #at_rand!, #pick, #pick!, #rand_index, #rand_subarrays, #rand_subset, #shuffle, #shuffle!

Methods included from Indexable

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

Class Method Details

.zip(*arrays) ⇒ Object

Class level rendition of Array#zip.

arrays - List of arrays to zip. [Array<Array>]

Example:

Array.zip([1,2],[3,4]]
#=> [[1,3],[2,4]]

Returns arranged array of arrays. [Array<Array>]

Returns an empty array if no arguments are given. [Array]



16
17
18
19
# File 'lib/core/facets/array/zip.rb', line 16

def self.zip(*arrays)
  return [] if arrays.empty?
  return arrays[0].zip(*arrays[1..-1])
end

Instance Method Details

#after(value) ⇒ Object

Returns the value after the given value. The value before the last is the first. Returns nil if the given value is not in the array.

Examples

sequence = ['a', 'b', 'c']
sequence.after('a')           #=> 'b'
sequence.after('b')           #=> 'c'
sequence.after('c')           #=> 'a'
sequence.after('d')           #=> nil

CREDIT: Tyler Rick



35
36
37
38
# File 'lib/core/facets/array/before.rb', line 35

def after(value)
  return nil unless include? value
  self[(index(value).to_i + 1) % length]
end

#arrangeObject Also known as: rangify

The `arrange` method produces appropriate ranges from the objects in the array.

Examples

[1,2,3,6,7,8].arrange  #=> [1..3, 6..8]

[10..15, 16..20, 21, 22].arrange  #=> [10..22]

Assumes inclusive ranges (ie. 1..4) and range.first <= range.last.

Works with integers, dates and strings. However, all the objects in the array must be of the same class.

CREDIT: monocle



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/core/facets/array/arrange.rb', line 18

def arrange
	array = uniq.sort_by { |e| Range === e ? e.first : e }
	array.inject([]) do |c, value|
		unless c.empty?
			last = c.last
			last_value    = (Range === last  ? last.last   : last)
			current_value = (Range === value ? value.first : value)
			if (last_value.succ <=> current_value) == -1
				c << value
			else
				first  = (Range === last ? last.first : last)
				second = [Range === last ? last.last : last, Range === value ? value.last : value].max
				c[-1] = [first..second]
				c.flatten!
			end
		else
			c << value
		end
	end
end

#before(value) ⇒ Object

Returns the value previous to the given value. The value previous to the first is the last. Returns nil if the given value is not in the array.

Examples

sequence = ['a', 'b', 'c']
sequence.before('a')           #=> 'c'
sequence.before('b')           #=> 'a'
sequence.before('c')           #=> 'b'
sequence.before('d')           #=> nil

CREDIT: Tyler Rick



17
18
19
20
# File 'lib/core/facets/array/before.rb', line 17

def before(value)
  return nil unless include? value
  self[(index(value).to_i - 1) % length]
end

#collapseObject

Simplify an array by flattening it then compacting it.

Examples

[1,[2,nil,[3]],nil,4].collapse  #=> [1,2,3,4]


9
10
11
# File 'lib/core/facets/array/collapse.rb', line 9

def collapse
  flatten.compact
end

#commonality(&block) ⇒ Object Also known as: collisions

Get a list of all items that have something in common in terms of the supplied block. If no block is given objects are considered to be in common if they return the same value for Object#hash and if obj1 == obj2.

This can be useful, for instance, in determining all persons that share their last name with another person.

persons.commonality { |person| person.last_name }

The method is similar to #group_by which is a standard Ruby method as of 1.9. To get effectively the same results with #group_by use `select{ |k,v| v.size > 1 }`.

[1, 2, 2, 3, 4, 4].group_by{ |e| e }.select{ |k,v| v.size > 1 }
#=> { 2 => [2, 2], 4 => [4, 4] }

Examples

[1, 2, 2, 3, 4, 4].commonality  #=> { 2 => [2, 2], 4 => [4, 4] }

["foo", "bar", "baz"].commonality { |str| str[0] }
#=> { 'b' => ["bar", "baz"] }

Returns [Hash] mapping common attribute to those elements.

CREDIT: Florian Gross



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/core/facets/array/commonality.rb', line 29

def commonality(&block)
  block ||= lambda { |item| item }

  result = Hash.new { |hash, key| hash[key] = Array.new }
  each do |item|
    key = block.call(item)
    result[key] << item
  end

  result.reject! do |key, values|
    values.size <= 1
  end

  return result
end

#conjoin(*args, &block) ⇒ Object

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

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

If no paramters are given, it acts like #join but will a space separator.

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

Use comma+space and 'and' on tail.

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

Use comma+space and 'or' on tail using :last option.

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

Use semicolon+space and ampersand on tail using index.

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

Can take a block to determine separator.

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

This makes very esoteric transformation possible.

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

[1,2,3,4].conjoin{ |i, x, y| "<#{i} #{x} #{y}>" }
#=> "1<0 1 2>2<1 2 3>3<2 3 4>4"

There are also spacing options. Providing the :space option pads the separators.

[1,2,3].conjoin(',', '&', :space=>2)
#=> "1  ,  2  &  3"

And the :spacer option can set an alternate spacing string.

[1,2,3].conjoin('|', '>', :space=>2, :spacer=>'-')
#=> "1--|--2-->--3"

CREDIT: Trans



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/core/facets/array/conjoin.rb', line 57

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

  options = (Hash===args.last) ? args.pop : {}

  spacing = options.delete(:space)  || 0
  spacer  = options.delete(:spacer) || " "
  space   = spacer * spacing.to_i

  sep = []

  if block_given?
    (size - 1).times do |i|
      sep << space + yield(i, *slice(i,2)) + space
    end
  else
    separator   = args.shift || " "
    options[-1] = args.shift if args.first

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

    separator = space + separator + space

    sep = [separator] * (size - 1)

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

#delete_unless(&block) ⇒ Object

Inverse of #delete_if.

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

CREDIT: Daniel Schierbeck



10
11
12
# File 'lib/core/facets/array/delete_unless.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



11
12
13
14
15
# File 'lib/core/facets/array/delete_values.rb', line 11

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



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/core/facets/array/delete_values.rb', line 32

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

#divide(pattern) ⇒ Object

Divide on matching pattern.

['a1','b1','a2','b2'].divide(/^a/)
#=> [['a1','b1'],['a2','b2']]

CREDIT: Trans



10
11
12
13
14
15
16
17
# File 'lib/core/facets/array/divide.rb', line 10

def divide(pattern)
  memo = []
  each do |obj|
    memo.push [] if pattern === obj
    memo.last << obj
  end
  memo
end

#duplicates(min = 2) ⇒ Object

Return list of duplicate elements.

min - The minimum number of duplication necessary for inclusion. [Integer]

Examples:

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

CREDIT: Rebort Dober (current implementation) CREDIT: Thibaut Barrère



14
15
16
17
18
19
20
# File 'lib/core/facets/array/duplicates.rb', line 14

def duplicates(min=2)
  h = Hash.new( 0 )
  each {|i|
    h[i] += 1
  }
  h.delete_if{|_,v| v < min}.keys
end

#each_overlap(slice_size, overlap) ⇒ Object

Iterate over each slice where the last n values of a preceding slice overlap with the first n values of the following slice. The value of n is specified by the second `overlap` argument.

a, r = [1,2,3,4,5], []
a.each_overlap(2,1) { |x,y| r << [x,y] } 
r # => [[1,2],[2,3],[3,4],[4,5]]

Returns nothing.



13
14
15
16
17
18
19
20
21
22
23
# File 'lib/core/facets/array/each_overlap.rb', line 13

def each_overlap(slice_size, overlap)
  if block_given?
  i = 0
  while i + slice_size <= length
    yield slice(i...i+slice_size)
    i += (slice_size - overlap)
  end
  else
    to_enum(:each_overlap, slice_size, overlap)
  end
end

#each_pairObject

Iterate over index and value. The intention of this method is to provide polymorphism with Hash.



6
7
8
9
10
11
# File 'lib/core/facets/array/each_pair.rb', line 6

def each_pair #:yield:
  i = -1
  each_value do |x|
    yield(i+=1, x)
  end
end

#entropyObject

Shannon's entropy for an array - returns the average bits per symbol required to encode the array. Lower values mean less “entropy” - i.e. less unique information in the array.

e = %w{ a b c d e e e }.entropy

("%.3f" % e)  #=> "2.128"

CREDIT: Derek



16
17
18
19
20
21
22
23
24
# File 'lib/core/facets/array/entropy.rb', line 16

def entropy
  arr = self
  probHash = arr.probability
  # -- h is the Shannon entropy of the array
  h = -1.to_f * probHash.keys.inject(0.to_f) do |sum, i|
    sum + (probHash[i] * (Math.log(probHash[i])/Math.log(2.to_f)))
  end
  h
end

#extract_options!Object

Extracts options from a set of arguments. Removes and returns the last element in the array if it's a hash, otherwise returns a blank hash.

def options(*args)
  args.extract_options!
end

options(1, 2)           # => {}
options(1, 2, :a => :b) # => {:a=>:b}


23
24
25
26
27
28
29
# File 'lib/core/facets/array/extract_options.rb', line 23

def extract_options!
  if Hash === last && last.extractable_options?
    pop
  else
    {}
  end
end

#from(i) ⇒ Object



7
8
9
10
# File 'lib/core/facets/array/from.rb', line 7

def from(i)
  return self if i >= size
  self[i, size - i]
end

#ideal_entropyObject

Returns the maximum possible Shannon entropy of the array with given size assuming that it is an “order-0” source (each element is selected independently of the next).

CREDIT: Derek



32
33
34
35
36
# File 'lib/core/facets/array/entropy.rb', line 32

def ideal_entropy
  arr = self
  unitProb = 1.0.to_f / arr.size.to_f
  (-1.to_f * arr.size.to_f * unitProb * Math.log(unitProb)/Math.log(2.to_f))
end

#intersectionObject

CREDIT: monocle



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/core/facets/array/intersection.rb', line 7

def intersection
	array = uniq.sort_by { |e| Range === e ? e.first : e }
	array.inject() do |c, e|
		f = (Range === c ? c.last  : c)
		v = (Range === e ? e.first : e)
		case f <=> v
		when -1 then return nil
		when  0 then f
		else
			if Range === e
				v..([f, e.last].min)
			else
				v
			end
		end
	end
end

#median(offset = 0) ⇒ Object

Determines the sorted middle element.

a = %w{a a b b c c c}
a.median     #=> "b"

When there are an even number of elements, the greater of the two middle elements is given.

a = %w{a a b b c c c d}
a.median     #=> "c"

An offset can be supplied to get an element relative to the middle.

a = %w{a a b b c c c d}
a.median(-1) #=> "b"

The the array is empty, nil is returned.

Returns:

  • (Object)

    sorted middle element



23
24
25
26
27
28
29
30
# File 'lib/core/facets/array/median.rb', line 23

def median(offset=0)
  return nil if self.size == 0

  tmp = self.sort
  mid = (tmp.size / 2).to_i + offset

  tmp[mid]
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/core/facets/array/merge.rb', line 11

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

#missingObject

CREDIT: monocle



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/core/facets/array/missing.rb', line 13

def missing
	missing, array = [], arrange
	i, length = 0, array.size - 1
	while i < length 
     x0 = array[i]
     x1 = array[i+1]
		c = (Range === x0 ? x0.last  : x0)
		n = (Range === x1 ? x1.first : x1)
		missing << (
       c.succ.succ == n ? c.succ : ((c.succ)..(n.pred))
     )
		i += 1
	end
   return missing
end

#modeObject

In Statistics mode is the value that occurs most frequently in a given set of data. This method returns an array in case their is a tie.

[:a, :b, :c, :b, :d].mode  #=> [:b]
[:a, :b, :c, :b, :a].mode  #=> [:a, :b]

Returns an Array of most common elements.

Author:

  • Robert Klemme



14
15
16
17
18
19
# File 'lib/core/facets/array/mode.rb', line 14

def mode
  max = 0
  c = Hash.new 0
  each {|x| cc = c[x] += 1; max = cc if cc > max}
  c.select {|k,v| v == max}.map {|k,v| k}
end

#nonuniqObject

Returns a list of non-unique elements.

Examples

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

CREDIT: Martin DeMello



11
12
13
14
15
16
17
18
19
# File 'lib/core/facets/array/nonuniq.rb', line 11

def nonuniq
  h1 = {}
  h2 = {}
  each {|i|
    h2[i] = true if h1[i]
    h1[i] = true
  }
  h2.keys
end

#nonuniq!Object

Same as `#nonuniq` but acts in place.



23
24
25
# File 'lib/core/facets/array/nonuniq.rb', line 23

def nonuniq!
  self.replace(self.nonuniq)
end

#not_empty?Boolean

Not empty?

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

Returns:

  • (Boolean)


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

def not_empty?
  !empty?
end

#object_state(data = nil) ⇒ Object



47
48
49
# File 'lib/core/facets/object/object_state.rb', line 47

def object_state(data=nil)
  data ? replace(data) : dup
end

#occur(n = nil) ⇒ Object Also known as: occurs

Returns a list of elements that occur n times.

If n is a Range then returns elements that occur a number of time within the range.

Examples

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

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

Returns [Array] of reoccurring elements.

CREDIT: Robert Dober



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/core/facets/array/occur.rb', line 18

def occur(n=nil) #:yield:
  h = Hash.new(0)

  each do |i|
    h[i] += 1
  end

  case n
  when nil
    h.delete_if{ |_,v| ! yield(v) }.keys
  when Range
    h.delete_if{ |_,v| ! n.include?(v) }.keys
  else
    h.delete_if{|_,v| v != n}.keys
  end
end

#occurrenceObject

Create a hart of counts of duplicate elements.

Examples

[:a,:a,:b,:c,:c,:c].occurrence
#=> { :a => 2, :b => 1, :c => 3 } 

[2,2,3,4,4,4].occurence{|i| i % 2} 
#=> { 0 => 5, 1 => 1 }


13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/core/facets/array/occurrence.rb', line 13

def occurrence
  h = Hash.new(0)
  if block_given?
    each do |e|
      h[yield(e)] += 1
    end
  else
    each do |e|
      h[e] += 1
    end
  end
  h
end

#onlyObject

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

[5].only      # => 5

expect IndexError do
  [1,2,3].only
end

expect IndexError do
  [].only
end

CREDIT: Gavin Sinclair, Noah Gibbs



18
19
20
21
22
23
# File 'lib/core/facets/array/only.rb', line 18

def only
  unless size == 1
    raise IndexError, "not the only element of array"
  end
  first
end

#only?Boolean

Does this Array have only one element?

TODO: While clearly this goes along with the regular #only method, the name doesn't seem quite right. Perhaps rename to #lonely.

CREDIT: Lavir the Whiolet

Returns:

  • (Boolean)


32
33
34
# File 'lib/core/facets/array/only.rb', line 32

def only?
  size == 1
end

#pad(len, val = nil) ⇒ Object

Pad an array with a given value up to 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/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/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

#peek(i = 0) ⇒ Object

Peek at the top of the stack (the end of the array).

a = [1, 2, 3]
a.peek          #=> 3
a               #=> [1, 2, 3]

Or provide an index to inspect the array from back to front.



14
15
16
17
# File 'lib/core/facets/array/pull.rb', line 14

def peek(i=0)
  i = -(i + 1)
  fetch(i)
end

#poke(x, i = 0) ⇒ Object

Put an object on the bottom of the stack (front of the array).

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

Or supply an index and #poke works like #insert.



26
27
28
# File 'lib/core/facets/array/pull.rb', line 26

def poke(x, i=0)
  insert(i,x)
end

#power_setObject

Author:

  • Phrogz



24
25
26
27
28
29
30
31
32
33
# File 'lib/standard/facets/set.rb', line 24

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

#probabilityObject

Generates a hash mapping each unique element in the array to the relative frequency, i.e. the probablity, of it appearence.

[:a, :b, :c, :c].probability  #=> {:a=> 0.25, :b=>0.25, :c=>0.5}

CREDIT: Brian Schröder



10
11
12
13
14
15
16
17
18
19
# File 'lib/core/facets/array/probability.rb', line 10

def probability
  probs = Hash.new(0.0)
  size = 0.0
  each do |e|
    probs[e] += 1.0
    size += 1.0
  end
  probs.keys.each{ |e| probs[e] /= size }
  probs
end

#recurse(*types) {|a| ... } ⇒ Object

Apply a block to array, and recursively apply that block to each sub-array or types.

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

Yields:

  • (a)


10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/core/facets/array/recurse.rb', line 10

def recurse(*types, &block)
  types = [self.class] if types.empty?
  a = inject([]) do |array, value|
    case value
    when *types
      array << value.recurse(*types, &block)
    else
      array << value
    end
    array
  end
  yield a
end

#recurse!(&block) ⇒ Object

In place form of #recurse.



25
26
27
# File 'lib/core/facets/array/recurse.rb', line 25

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

#recursively(*types, &block) ⇒ Object

Apply a method to array, and recursively apply that method to each sub-array or given types.

By default the sub-types are passed thru uneffected. Passing a block to #recursively can be used to change this.

types - List of class types to recurse. [Array<Class>] block - Optional filter procedure to apply on each recursion.

Examples

arr = ["a", ["b", "c"]]
arr.recursively.map{ |v| v.to_sym }
#=> [:a, [:b, :c]]

arr = ["a", ["b", "c"]]
arr.recursively{ |a| a.reverse }.map{ |v| v.to_sym }
#=> [:a, [:c, :b]]

Returns [Recursor].



27
28
29
# File 'lib/core/facets/array/recursively.rb', line 27

def recursively(*types, &block)
  Recursor.new(self, *types, &block)
end

#reject_values(*values) ⇒ Object

Non-destructive form of `Array#delete_values`. Unlike `delete_values` this method returns a new array.

values - List of array elements to reject.

Examples

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

Returns [Array]

CREDIT: Sean Mackesey



16
17
18
# File 'lib/core/facets/array/reject_values.rb', line 16

def reject_values(*values)
  reject { |x| values.include?(x) }
end

#shelljoinObject



81
82
83
# File 'lib/standard/facets/shellwords.rb', line 81

def shelljoin
  Shellwords.shelljoin(shellwords)
end

#shellwordsObject

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



74
75
76
77
78
# File 'lib/standard/facets/shellwords.rb', line 74

def shellwords
  opts, args = *flatten.partition{ |e| Hash === e }
  opts = opts.inject({}){ |m,h| m.update(h); m }
  opts.shellwords + args
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 given it calls slice!.

Examples

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

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

Returns [Array].

CREDIT: Trans



23
24
25
26
27
28
29
# File 'lib/core/facets/array/splice.rb', line 23

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

#split(pattern) ⇒ Object

Split on matching pattern. Unlike #divide this does not include matching elements.

Examples

['a1','a2','b1','a3','b2','a4'].split(/^b/)
#=> [['a1','a2'],['a3'],['a4']]

Returns list of split-up arrays. [Array<Array>]



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/core/facets/array/split.rb', line 13

def split(pattern)
  memo = []
  sect = []
  each do |obj|
    if pattern === obj
      memo << sect
      sect = []
    else
      sect << obj
    end
  end
  memo << sect
  memo.pop while memo.last == []
  memo
end

#squeeze!(*limited_to) ⇒ Object

Destructive version of Enumerable#squeeze.

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

a = [1,2,2,3,3,2,1]
a.squeeze!(*[3])
a #=> [1,2,2,3,2,1]

Returns the receiver. [Array]

CREDIT: T. Yamada



19
20
21
# File 'lib/core/facets/array/squeeze.rb', line 19

def squeeze!(*limited_to)
  replace(squeeze(*limited_to))
end

#step(n) ⇒ Object

Iterate over every nth element of an array.

r = []
[:a, :b, :c, :d].step(2) { |x| r << x }
r   #=> [:b, :d]

Without a block it returns an Enumerator.

[:a, :b, :c, :d].step(1).to_a   #=> [:a, :b, :c, :d]
[:a, :b, :c, :d].step(2).to_a   #=> [:b, :d]
[:a, :b, :c, :d].step(3).to_a   #=> [:c]
[:a, :b, :c, :d].step(5).to_a   #=> []

CREDIT: Ryan Duryea



18
19
20
21
22
23
24
25
26
27
28
# File 'lib/core/facets/array/step.rb', line 18

def step(n) #:yield:
  if block_given?
    ((n - 1)...size).step(n).each do |i|
      yield(fetch(i))
    end
  else
    Enumerator.new(size / n) do |y|
      ((n - 1)...self.size).step(n).each { |i| y << fetch(i) }  
    end
  end
end

#thru(from, to = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/core/facets/array/from.rb', line 20

def thru(from, to=nil)
  from, to = 0, from unless to
  to = size - 1 if to >= size
  a = []
  i = from
  while i <= to
    a << self[i]
    i += 1
  end
  a
end

#to_bObject

Boolean conversion for not empty?



110
111
112
# File 'lib/core/facets/boolean.rb', line 110

def to_b
  ! self.empty?
end

#to_hObject



15
16
17
18
19
# File 'lib/core/facets/array/to_h.rb', line 15

def to_h
  h = {}
  each{ |(k,v)| h[k] = v }
  h
end

#to_pathObject

Convert array to Pathname instance.

Standard:

  • require 'facets/pathname'



24
25
26
# File 'lib/standard/facets/pathname/to_path.rb', line 24

def to_path
  Pathname.new(join('/'))
end

#to_tObject

Convert an array into a tuple.



276
277
278
# File 'lib/standard/facets/tuple.rb', line 276

def to_t
  Tuple.cast_from_array( self )
end

#traverse(&block) ⇒ Object

Construct a new array created by traversing the array and its sub-arrays, executing the given block on the elements.

Examples

h = ["A", "B", ["X", "Y"]]
g = h.traverse{ |e| e.downcase }
g  #=> ["a", "b", ["x", "y"]]

This is the same as recursive.map and will likely be deprecated in the future because of it.

Returns new array. [Array]

CREDIT: Trans



19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/core/facets/array/traverse.rb', line 19

def traverse(&block)
  if block_given?
    map do |e|
      if e.respond_to?(:to_ary)
        e.to_ary.traverse(&block)
      else
        block.call(e)
      end
    end
  else
    to_enum(:traverse)
  end
end

#traverse!(&block) ⇒ Object

Like #recursive_map, but will change the array in place.

Examples:

h = ["A", "B", ["X", "Y"]]
h.traverse!{ |e| e.downcase }
h  #=> ["a", "b", ["x", "y"]]

Returns self. [Array]

CREDIT: Trans



45
46
47
# File 'lib/core/facets/array/traverse.rb', line 45

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

#uniq_by!Object

Like #uniq, but determines uniqueness based on a given block. As can be seen in the following examples, order is significant.

Examples

a = (-5..5).to_a
a.uniq_by!{ |i| i*i }
a #=> [-5, -4, -3, -2, -1, 0]

Returns [Array] of unique elements.



14
15
16
17
# File 'lib/core/facets/array/uniq_by.rb', line 14

def uniq_by! #:yield:
  h = {}
  replace( inject([]){|a,x| h[yield(x)] ||= a << x} )
end

#unique_permutation(n = self.size) {|a[0,n]| ... } ⇒ Object

Enumerates permutation of Array. Unlike Array#permutation, there are no duplicates in generated permutations. Instead, elements must be comparable.

[1,1,2,2,3].unique_permutation(2).to_a
#=> [[1, 1], [1, 2], [1, 3], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2]]
# Note: [1,1,2,2,3].permutation(2).to_a
#=> [[1, 1], [1, 2], [1, 2], [1, 3], [1, 1], [1, 2], [1, 2], [1, 3], [2, 1], [2, 1], [2, 2], [2, 3], [2, 1], [2, 1], [2, 2], [2, 3], [3, 1], [3, 1], [3, 2], [3, 2]]

CREDIT: T. Yamada

Yields:

  • (a[0,n])


13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/core/facets/array/unique_permutation.rb', line 13

def unique_permutation(n=self.size)
  return to_enum(:unique_permutation,n) unless block_given?
  return if n<0||self.size<n
  a=self.sort # sort is O(nlogn), so I believe this is not so costly. (Also sort is not destructive)
  yield a[0,n]
  loop{
    a=a[0,n]+a[n..-1].reverse
    k=(a.size-2).downto(0).find{|i|a[i]<a[i+1]}
    break if !k
    l=(a.size-1).downto(k+1).find{|i|a[k]<a[i]}
    a[k],a[l]=a[l],a[k]
    a=a[0,k+1]+a[k+1..-1].reverse
    yield a[0,n]
  }
end