Array.invert

I would like to see invert “rubyfied”.
(Yes, I’m trying to get a grip of what this word means :slight_smile:

class Array
def invert
res=[]
for i in 0…self.size
if self[i] != nil then
for b in self[i]
res[b] = [] if res[b].nil?
res[b] << i
end
end
end
res
end
end

require ‘test/unit’
class TestArray < Test::Unit::TestCase
def test_invert_1
a = [[1,3],[1,4,5]]
b = [nil,[0,1],nil,[0],[1],[1]]
assert_equal b,a.invert
assert_equal a,b.invert
end

def test_invert_2
a = []
a << [3,9,13] # 0
a << [3,11,14] # 1
a << [3,14,15] # 2
a << [4,1,4] # 3
a << [4,8,9] # 4
a << [5,0,1] # 5
a << [6,6,7] # 6
a << [14,2,6] # 7
a << [10,5,8,12,15] # 8
a << [10,10,11,12,13] # 9
a << [11,0,3,7,10] # 10
a << [17,2,3,4,5] # 11

# behead...
c = a.map {|head, *tail| tail}

b = []
b << [5,10] # 0
b << [3,5]  # 1
b << [7,11] # 2
b << [10,11]# 3
b << [3,11] # 4
b << [8,11] # 5
b << [6,7]  # 6
b << [6,10] # 7
b << [4,8]  # 8
b << [0,4]  # 9
b << [9,10] # 10
b << [1,9]  # 11
b << [8,9]  # 12
b << [0,9]  # 13
b << [1,2]  # 14
b << [2,8]  # 15

assert_equal b,c.invert
assert_equal c,b.invert

end
end

Christer

Hi –

On Tue, 13 Dec 2005, Christer N. wrote:

I would like to see invert “rubyfied”.
(Yes, I’m trying to get a grip of what this word means :slight_smile:

Aren’t we all? But the trying is so much fun :slight_smile:

Here’s a version that might be more idiomatic, and that passes all
your tests:

class Array
def invert
res=[]
each_with_index do |e,i|
if e
e.each do |f|
(res[f] ||= []) << i
end
end
end
res
end
end

David


David A. Black
[email protected]

“Ruby for Rails”, forthcoming from Manning Publications, April 2006!

Christer N. wrote:

      res[b] << i
    end
  end
end
res

end
end

I suggest

class Array
def invert
result = []
each_with_index do |ary, idx|
next if ary.nil?
ary.each {|val| (result[val] ||= []).push(idx)}
end
result
end
end

As a matter of taste, you may want to write the two middle
lines in just one line as

   ary.each {|val| (result[val] ||= []).push(idx)} unless ary.nil?

HTH,

Michael

Beautiful, thank you David and Michael.
Must be hard to improve now!

[David, Michael].merge :

class Array
def invert
res = []
each_with_index do |e, i|
e.each {|f| (res[f] ||= []) << i} if e
end
res
end
end

Christer

Hash.invert exists, returning another Hash.

Is there any other interesting interpretation of Array.invert ?

(Matrix.invert is another thing :slight_smile:

Is Array.invert useful enough to be a part of the original set of
methods of Array?

I see two reasons for building in methods,
the first one is to make programmer code faster,
the second is to make code execute faster.

If Array.invert is seldom used and possible to execute fast, already in
Ruby, there is no good reason to build it in.

Personally, I used Array.invert in finding solutions for kakuro.

Christer