Last active
August 30, 2018 15:27
-
-
Save sancarn/09b0f29a61fb6a86ebe7c0be48576799 to your computer and use it in GitHub Desktop.
Piles are a great way of updating all values of a set at once, instead of mapping arrays constantly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
Piles are a great way of updating all values of a set at once, instead of mapping arrays constantly. | |
E.G. | |
Example CSV: | |
a,b,c | |
1,2,3 | |
4,5,6 | |
Then: | |
csv=CSV.new(text, {:headers=>true}) | |
pileA = csv.pile_column(:a) | |
pileA #=> [1,4] | |
pileA + 2 #=> [3,6] | |
pileA * 2 #=> [2,8] | |
pileA / 2 #=> [0,2] | |
pileA < 2 #=> [true,false] | |
pileB = csv.pile_column(:b) | |
pileA + pileB #=>[3,9] | |
pileA * pileB #=>[2,20] | |
#... | |
#You can also create piles from arrays: | |
pileX = [4,1].to_pile | |
pileA + pileX #=> [5,5] | |
=end | |
module ::Math | |
class Pile < ::Array | |
#Operator wrapper: | |
def operate_each(vec,func_or_operator) | |
if !func_or_operator.is_a?(::Symbol) | |
raise "Function or Operator must be a symbol" | |
end | |
if vec.is_a? ::Array | |
if self.length == vec.length | |
arr = self.class.new([]) | |
self.each_with_index do |part,index| | |
arr.push(part.__send__(func_or_operator,vec[index])) | |
end | |
return arr | |
else | |
raise "If 1st argument is an array then it should be the same length as source." | |
end | |
else | |
arr = self.class.new([]) | |
self.each do |part| | |
arr.push(part.__send__(func_or_operator,vec)) | |
end | |
return arr | |
end | |
end | |
#HACK: | |
#Defining overrides - Used to do this dynamically but had trouble | |
def +(vec) | |
operate_each(vec,:+) | |
end | |
def -(vec) | |
operate_each(vec,:-) | |
end | |
def *(vec) | |
operate_each(vec,:*) | |
end | |
def /(vec) | |
operate_each(vec,:/) | |
end | |
def **(vec) | |
operate_each(vec,:**) | |
end | |
def &(vec) | |
operate_each(vec,:&) | |
end | |
def |(vec) | |
operate_each(vec,:|) | |
end | |
def ^(vec) | |
operate_each(vec,:^) | |
end | |
def >(vec) | |
operate_each(vec,:>) | |
end | |
def <(vec) | |
operate_each(vec,:<) | |
end | |
def <=(vec) | |
operate_each(vec,:<=) | |
end | |
def >=(vec) | |
operate_each(vec,:>=) | |
end | |
def ==(vec) | |
operate_each(vec,:==) | |
end | |
def ===(vec) | |
operate_each(vec,:===) | |
end | |
#Not inverts all of the current pile's values | |
def not | |
self.map {|val| !val}.to_pile | |
end | |
def map(*args) | |
super(*args).to_pile | |
end | |
def max | |
max=-1*Float::INFINITY | |
self.each do |el| | |
if el > max | |
max = el | |
end | |
end | |
if max==-1*Float::INFINITY | |
return nil | |
else | |
return max | |
end | |
end | |
def min | |
min=Float::INFINITY | |
self.each do |el| | |
if el < min | |
min = el | |
end | |
end | |
if min==Float::INFINITY | |
return nil | |
else | |
return min | |
end | |
end | |
def to_s | |
return self.join(",") | |
end | |
def initialize(arr) | |
super(0,0) | |
arr.each do |el| | |
self.push(el) | |
end | |
end | |
end | |
end | |
class ::Array | |
def to_pile | |
::Math::Pile.new(self) | |
end | |
end | |
class ::CSV | |
def pile_column(header_or_id) | |
self.rewind | |
return self.map do |row| | |
row[header_or_id] | |
end.to_pile | |
end | |
def pile_row(rowid) | |
self.rewind | |
self.each_with_index do |ro,id| | |
if id==rowid | |
return ro.to_a.to_pile | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment