Class: Array

Inherits:
Object show all
Defined in:
lib/nuggets/array/only.rb,
lib/nuggets/array/rand.rb,
lib/nuggets/array/format.rb,
lib/nuggets/object/blank.rb,
lib/nuggets/array/shuffle.rb,
lib/nuggets/array/to_hash.rb,
lib/nuggets/array/in_order.rb,
lib/nuggets/array/monotone.rb,
lib/nuggets/array/combination.rb,
lib/nuggets/array/flatten_once.rb

Overview

#

A component of ruby-nuggets, some extensions to the Ruby programming # language. #

#

Copyright © 2007 Jens Wille #

#

Authors: #

Jens Wille <jens.wille@uni-koeln.de>                                    #
                                                                        #

ruby-nuggets is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the Free # Software Foundation; either version 3 of the License, or (at your option) # any later version. #

#

ruby-nuggets is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for # more details. #

#

You should have received a copy of the GNU General Public License along # with ruby-nuggets. If not, see <www.gnu.org/licenses/>. #

#

++

Instance Method Summary collapse

Instance Method Details

#%(args) ⇒ Object

call-seq:

array % other_array => aString
array % str         => aString

Format–Uses the first string in array for which the corresponding combination of other_array does not contain blank elements as a format specification, and returns the result of applying it to that combination (cf. String#%). Returns an empty string if other_array is empty.

Applies to string argument accordingly: First string in array applied to str; empty string if str is empty.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/nuggets/array/format.rb', line 43

def %(args)
  opts = { :sep => ', ' }
  opts.update(pop) if last.is_a?(Hash)

  default = lambda { |n|
    ['%s'] * n * opts[:sep]
  }

  case args
    when String
      return (first || default[1]) % args unless
        args.nil? || args.empty?
    when Array
      i = 0
      [*args].comb { |x|
        return (self[i] || default[x.size]) % x unless
          x.empty? || x.any? { |y|
            y.nil? || y.empty?
          }

        i += 1
      }
  end

  ''
end

#ascending?(strict = false) ⇒ Boolean Also known as: increasing?

call-seq:

array.ascending? => true or false

Check whether array is (strictly) ascending.

Returns:

  • (Boolean)


48
49
50
# File 'lib/nuggets/array/monotone.rb', line 48

def ascending?(strict = false)
  monotone?(strict ? :< : :<=)
end

#comb(*sizes) ⇒ Object

call-seq:

array.comb(n, ...) => new_array
array.comb(n, ...) { |combination| ... } => new_array

Returns an array of arrays of each possible n-combination of array for each given n. If a block is given, each combination is yielded to it. Based on <blade.nagaokaut.ac.jp/~sinara/ruby/math/combinatorics/array-comb.rb>.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/nuggets/array/combination.rb', line 37

def comb(*sizes)
  # If no sizes are given, produce all!
  sizes = (0..size).to_a.reverse if sizes.empty?

  # Container for our combinations
  combinations = []

  # Collect combinations and, optionally, yield to block.
  collect_and_yield = lambda { |combination|
    combinations << combination

    yield(combination) if block_given?
  }

  sizes.each { |n|
    case n
      when 0        # Short-cut (breaks recursion)
        collect_and_yield[[]]
      when 1..size  # Ignore out-of-range values
        self[1..-1].comb(n - 1) { |combination|
          collect_and_yield[combination.unshift(first)]
        }
        self[1..-1].comb(n) { |combination|
          collect_and_yield[combination]
        }
    end
  }

  # Anyway, return what we've found...
  combinations
end

#descending?(strict = false) ⇒ Boolean Also known as: decreasing?

call-seq:

array.descending? => true or false

Check whether array is (strictly) descending.

Returns:

  • (Boolean)


66
67
68
# File 'lib/nuggets/array/monotone.rb', line 66

def descending?(strict = false)
  monotone?(strict ? :> : :>=)
end

#flatten_onceObject

call-seq:

array.flatten_once => new_array

Flatten array by one level only. Pretty straight-forward port of David Alan Black’s flattenx C implementation (though much slower, of course ;-).



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/nuggets/array/flatten_once.rb', line 35

def flatten_once
  flat = []

  each { |element|
    if element.is_a?(Array)
      flat += element
    else
      flat << element
    end
  }

  flat
end

#flatten_once!Object

call-seq:

array.flatten_once! => array

Destructive version of #flatten_once.



53
54
55
# File 'lib/nuggets/array/flatten_once.rb', line 53

def flatten_once!
  replace flatten_once
end

#in_order(*ordered) ⇒ Object

call-seq:

array.in_order(*ordered) => new_array

Force order, but ignore non-existing and keep remaining.

Examples:

[:created_at, :email, :login, :updated_at].in_order(:login, :email)    #=> [:login, :email, :created_at, :updated_at]
[:created_at, :email, :login, :updated_at].in_order(:email, :address)  #=> [:email, :created_at, :login, :updated_at]


38
39
40
41
# File 'lib/nuggets/array/in_order.rb', line 38

def in_order(*ordered)
  ordered &= self
  ordered + (self - ordered)
end

#in_order!(*ordered) ⇒ Object

call-seq:

array.in_order!(*ordered) => array

Destructive version of #in_order.



47
48
49
# File 'lib/nuggets/array/in_order.rb', line 47

def in_order!(*ordered)
  replace in_order(*ordered)
end

#monotone?(operator) ⇒ Boolean Also known as: monotonic?

call-seq:

array.monotone?(operator) => true or false

Check whether array is monotone according to operator.

Returns:

  • (Boolean)


34
35
36
37
38
39
40
41
# File 'lib/nuggets/array/monotone.rb', line 34

def monotone?(operator)
  inject { |a, b|
    return false unless a.send(operator, b)
    b
  }

  true
end

#only(relax = size == 1) ⇒ Object

call-seq:

array.only(relax = true or false) => anObject

Returns the only element of array. Raises an IndexError if array’s size is not 1, unless relax is true.

Idea stolen from Gavin Sinclair’s Ruby Extensions Project.

Raises:

  • (IndexError)


37
38
39
40
# File 'lib/nuggets/array/only.rb', line 37

def only(relax = size == 1)
  raise IndexError, 'not a single-element array' unless relax
  first
end

#randObject

call-seq:

array.rand => anItem

Randomly pick an item from array.



34
35
36
# File 'lib/nuggets/array/rand.rb', line 34

def rand
  at(Kernel.rand(size))
end

#shuffleObject

call-seq:

array.shuffle => new_array

Shuffles array in random order. Select a different shuffling algorithm: Array.send(:alias_method, :shuffle, :shuffle_kfy).



35
36
37
# File 'lib/nuggets/array/shuffle.rb', line 35

def shuffle
  sort_by { Kernel.rand }
end

#shuffle!Object

call-seq:

array.shuffle! => array

Destructive version of #shuffle.



59
60
61
# File 'lib/nuggets/array/shuffle.rb', line 59

def shuffle!
  replace shuffle
end

#shuffle_kfyObject

call-seq:

array.shuffle_kfy => new_array

Non-destructive version of #shuffle_kfy!.



51
52
53
# File 'lib/nuggets/array/shuffle.rb', line 51

def shuffle_kfy
  dup.shuffle_kfy!
end

#shuffle_kfy!Object

call-seq:

array.shuffle_kfy! => array

Shuffles array in random order using the Knuth-Fisher-Yates algorithm.



80
81
82
83
84
85
86
87
# File 'lib/nuggets/array/shuffle.rb', line 80

def shuffle_kfy!
  (length - 1).downto(0) { |i|
    n = rand(i + 1)
    self[n], self[i] = self[i], self[n]
  }

  self
end

#shuffle_knuthObject

call-seq:

array.shuffle_knuth => new_array

Non-destructive version of #shuffle_knuth!.



43
44
45
# File 'lib/nuggets/array/shuffle.rb', line 43

def shuffle_knuth
  dup.shuffle_knuth!
end

#shuffle_knuth!Object

call-seq:

array.shuffle_knuth! => array

Shuffles array in random order using Knuth’s algorithm.



67
68
69
70
71
72
73
74
# File 'lib/nuggets/array/shuffle.rb', line 67

def shuffle_knuth!
  0.upto(length - 2) { |i|
    n = i + rand(length - i)
    self[i], self[n] = self[n], self[i]
  }

  self
end

#strictly_ascending?Boolean Also known as: strictly_increasing?

call-seq:

array.strictly_ascending? => true or false

Check whether array is strictly ascending.

Returns:

  • (Boolean)


57
58
59
# File 'lib/nuggets/array/monotone.rb', line 57

def strictly_ascending?
  ascending?(true)
end

#strictly_descending?Boolean Also known as: strictly_decreasing?

call-seq:

array.strictly_descending? => true or false

Check whether array is strictly descending.

Returns:

  • (Boolean)


75
76
77
# File 'lib/nuggets/array/monotone.rb', line 75

def strictly_descending?
  descending?(true)
end

#to_hash(value = default = Object.new) ⇒ Object Also known as: to_h

call-seq:

array.to_hash => aHash
array.to_hash(value) => aHash
array.to_hash { |element| ... } => aHash

If neither value nor block is given, converts array, taken as an array of key/value pairs, into a hash, preserving sub-arrays (Thus: hash.to_a.to_h == hash). Otherwise, maps each element of array to value or the result of the block.

Examples:

[[0, 0], [1, [2, 3]]].to_h  #=> { 0 => 0, 1 => [2, 3] }
%w[a b c d].to_h            #=> { "a" => "b", "c" => "d" }
%w[a b c d].to_h(1)         #=> { "a" => 1, "b" => 1, "c" => 1, "d" => 1 }
%w[a b].to_h { |e| e * 2 }  #=> { "a" => "aa", "b" => "bb" }


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/nuggets/array/to_hash.rb', line 47

def to_hash(value = default = Object.new)
  hash = {}

  if block_given?
    raise ArgumentError, "both block and value argument given" if default.nil?

    each { |element| hash[element] = yield element }
  elsif default.nil?
    each { |element| hash[element] = value }
  else
    return Hash[*flatten_once]
  end

  hash
end

#vain?Boolean

call-seq:

array.vain? => true or false

Returns true if all of array’s elements are themselves vain.

Returns:

  • (Boolean)


76
77
78
# File 'lib/nuggets/object/blank.rb', line 76

def vain?
  blank? { |a| a.delete_if { |i| i.vain? } }
end