Thursday, September 1, 2005

Array Slice

這幾天在看 Programming Ruby (2nd. Ed.)

看到 Array 部分時,好奇試了這些個東西

a = ["a", "b", "c", "d", "e"]
a[3, -2]
a[3..1]
a[-1..1]
a[-1..-3]

結果

a[3, -2] => nil
a[3..1] => []
a[-1..1] => []
a[-1..-3] => []

我想要是我來設計,大概會給它弄成這樣

a[3, -2] => ["d", "c"]
a[3..1] => ["d", "c", "b"]
a[-1..1] => ["e", "d", "c", "b"]
a[-1..-3] => ["e", "d", "c"]

因為既然負的 index 是由最後往前數(a[-1] => "e"),我會覺得取好幾個也要有由後往前取的功能 :P


  • 留言者: T55555
  • Email:
  • 網址:
  • 日期: 2005-09-01 19:21:15
Welcome to the Ruby World.





The [] rule is also apply to []=


So, if a = ['a', 'b', 'c', 'd', 'e']


and if a[3..1] => ['d', 'c', 'b']


What you would like to see if you write something like


a[3..1] = [1, 2, 3, 4] ?


a will become to ['a', 4, 3, 2, 1, 'e'] ?





One good thing about Ruby is everything are open.


Even the core library.


There are also calibre and facets project to change the array index to the way they like.





I can easily change the length negative value behavior as you like ( the Range one, leave to yourself to do it) , for example :





class Array

alias_method :old, :"[]"

def [](*args)  # define my new [] method for Array

begin

old(*args) unless args.length == 2 && args.last < 0

(0...-args.last).inject([]) { |a, i| a << self.slice(args.first - i) }

rescue

old(*args)

end

end

end



a = %w[a b c d e] #=> a = ['a', 'b', 'c', 'd', 'e']

a[3, -2]          #=> ['d', 'c']



So, if you don't like the default way, change to what you like.





On Ruby, you could even change 1+1 to become 3 if you like. :-)






  • 留言者: JiaYun
  • Email:
  • 網址:
  • 日期: 2005-09-01 20:41:12
Yes, I will let a be ['a', 4, 3, 2, 1, 'e'] after a[3..1] = [1, 2, 3, 4].





And I finished the homework, but only [] not []=.




class Array

alias_method :old, :"[]"

def [](*args)  # define my new [] method for Array

begin

if (args.length == 2 && args.last < 0)

(0...-args.last).inject([]) { |a, i| a << self.slice(args.first - i) }

elsif (args.length == 1 && args.first.class == Range)

range = args.first

first = range.first < 0 ? range.first + self.length : range.first

last = range.last < 0 ? range.last + self.length : range.last

if (first > last)

length = (first - last).abs

length += 1 unless range.exclude_end?

(0...length).inject([]) { |a, i| a << self.slice(range.first - i) }

else

old(*args)

end

else

old(*args)

end



rescue

old(*args)

end

end

end



a = %w[a b c d e]

a[-1..-3] #=> ["e", "d", "c"]

a[-1...-3] #=> ["e", "d"]

a[-1..1] #=> ["e", "d", "c", "b"]

a[-1...1] #=> ["e", "d", "c"]

a[4..2] #=> ["e", "d", "c"]

a[4...2] #=> ["e", "d"]







  • 留言者: T55555
  • Email: ruby55555@gmail.com
  • 網址:
  • 日期: 2005-09-02 00:09:54

Ooops, I found my bug ...


The line

old(*args) unless args.length == 2 && args.last < 0



should be like

return old(*args) unless args.length == 2 && args.last < 0

No comments:

Post a Comment