Ruby/Array/Array Extension

Материал из Wiki.crossplatform.ru

Перейти к: навигация, поиск

Содержание

Add a new method to Array class

class Array
 def each_from_both_sides
    front_index = 0
    back_index = self.length-1
    while front_index <= back_index
      yield self[front_index]
      front_index += 1
      if front_index <= back_index
    yield self[back_index]
        back_index -= 1
      end
    end
  end
end
new_array = []
[1,2,3,4,5].each_from_both_sides { |x| new_array << x }
p new_array                         # => [1, 5, 2, 4, 3]



Add method to Array class to convert an array to a hash

class Array
  def into_hash(h)
    unless size % 2 == 0
      raise StandardError, "Expected array with even number of elements"
    end
    0.step(size-1, 2) { |x| h[self[x]] = self[x+1] }
    h
  end
end
squares = [1,1,2,3,4,9]
results = {}
p squares.into_hash(results)                    # => {1=>1, 2=>3, 4=>9}
[1,1,2].into_hash(results)
# StandardError: Expected array with even number of elements



Add new operator for Array

class Array
  def ^(other)
    (self | other) - (self & other)
  end
end
x = [1, 2, 3, 4, 5]
y = [3, 4, 5, 6, 7]
z = x ^ y            # [1, 2, 6, 7]



Add shuffle method to Array class

class Array
  def shuffle!
    each_index do |i|
      j = rand(length-i) + i
      self[j], self[i] = self[i], self[j]
    end
  end
  def shuffle
    dup.shuffle!
  end
end



Add subset and superset operator for Array

class Array
  def subset?(other)
    self.each  do |x|
      if !(other.include? x)
        return false
      end
    end
    true
  end
  def superset?(other)
    other.subset?(self)
  end
end
a = [1, 2, 3, 4]
b = [2, 3]
c = [2, 3, 4, 5]
flag1 = c.subset? a     # false
flag2 = b.subset? a     # true
flag3 = c.superset? b   # true



Add your method to system data type

#!/usr/bin/env ruby
class Array
  def array_of_ten
    (1..10).to_a
  end
end
arr = Array.new
ten = arr.array_of_ten
p ten # => [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]



Array cartesian

module Enumerable
  def cartesian(other)
    res = []
    each { |x| other.each { |y| res << [x, y] } }
    return res
  end
end
p [1,2,3].cartesian(["a",5,6])
# => [[1, "a"], [1, 5], [1, 6],
# =>  [2, "a"], [2, 5], [2, 6],
# =>  [3, "a"], [3, 5], [3, 6]]



convert array to a hash

class Array
  def invert
    h={}
    self.each_with_index{|x,i| h[x]=i}
    h
  end
end
a = ["red","yellow","orange"]
h = a.invert     # {"orange"=>2, "yellow"=>1, "red"=>0}



each from both sides

class Array
 def each_from_both_sides()
    front_index = 0
    back_index = self.length-1
    while front_index <= back_index
      yield self[front_index]
      front_index += 1
      if front_index <= back_index
    yield self[back_index]
        back_index -= 1
      end
    end
  end
end
%w{1,2,3,4,5}.each_from_both_sides { |x| puts x }



Extends array comparsion method

class Array
  def <(other)
    (self <=> other) == -1
  end
  def <=(other)
    (self < other) or (self == other)
  end
  def >(other)
    (self <=> other) == 1
  end
  def >=(other)
    (self > other) or (self == other)
  end
end



Extract array in place

class Array
  def extract!
    ary = self.dup
    self.reject! { |x| yield x }
    ary - self
  end
end
p a = ("a".."h").to_a
p a.extract! { |x| x < "e" && x != "b" }     # => ["a", "c", "d"]
p a                # => ["b", "e", "f", "g", "h"]



Override array method

class Array2 < Array
  def [](index)
    if index>0
      super(index-1)
    else
      raise IndexError
    end
  end
  def []=(index,obj)
    if index>0
      super(index-1,obj)
    else
      raise IndexError
    end
  end
end
 
x = Array2.new
x[1]=5
x[2]=3
x[0]=1  # Error
x[-1]=1 # Error



Resequence the array

class Array
  def randomize
    arr=self.dup
    arr.collect { arr.slice!(rand arr.length) }
  end
  def randomize!
    arr=self.dup
    result = arr.collect { arr.slice!(rand arr.length) }
    self.replace result
  end
end
x = [1, 2, 3, 4, 5]
y = x.randomize      # [3, 2, 4, 1 ,5]
x.randomize!         # x is now [3, 5, 4, 1, 2]
class Array
  def pick_random
    self[rand(self.length)]
  end
end



Set permutation for Array

class Array
  def powerset
    num = 2**size
    ps = Array.new(num, [])
    self.each_index do |i|
      a = 2**i
      b = 2**(i+1) - 1
      j = 0
      while j < num-1
        for j in j+a..j+b
          ps[j] += [self[i]]
        end
        j += 1
      end
    end
    ps
  end
end
x = [1, 2, 3]
y = x.powerset
# y is now:
#   [[], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3]]



strip values from array

class Array
  def strip_values_at!(*args)
    args.each do |x|
      #For each mentioned index, replace its value with a dummy object.
      values = []
      dummy = Object.new
      args.each do |i|
        if i < size
          values << self[i]
          self[i] = dummy
        end
      end
      #Strip out the dummy object.
      delete(dummy)
      return values
    end
  end
end
p a = ("a".."h").to_a
p a.strip_values_at!(1, 0, -2)            # => ["b", "a", "g"]
p a                                       # => ["c", "d", "e", "f", "h"]
p a.strip_values_at!(1000)                # => []
p a                                       # => ["c", "d", "e", "f", "h"]



Use hash to count elements in an array

class Array
  def count
    k=Hash.new(0)
    self.each{|x| k[x]+=1 }
    k
  end
end
meal = %w[spam spam eggs ham eggs spam]
items = meal.count
# items is {"ham" => 1, "spam" => 3, "eggs" => 2}
spams = items["spam"]   # 3