Shreyas
Shreyas

Reputation: 8757

Finding indexes of each element in a multidimensional array in ruby

Eg

:a=[["hello", "world"], ["good", "lord"], ["hello", "lord"]]

I need to find and record the indexes of each word with respect to the super-array. i.e

hello => 0,2
world => 0
lord => 1,2.

here's my shot ,but its very amateurish and lengthy.

all_tokens=tokens.flatten
all_tokens.each do|keyword|                                                                                      
    tokens.each do|token_array|
        if token_array.include?keyword
            x << i
        end
        i=i+1
    end    
    y[k] = x.clone
    y=y.clear
end 

Upvotes: 2

Views: 4561

Answers (6)

Mladen Jablanović
Mladen Jablanović

Reputation: 44100

a.each_with_index.inject({}){|acc,(elem,i)|
  elem.each{|e|
    acc[e] ||= []
    acc[e] << i
  }
  acc
}
#=> {"hello"=>[0, 2], "world"=>[0], "good"=>[1], "lord"=>[1, 2]}

Upvotes: 2

fl00r
fl00r

Reputation: 83680

a=[["hello", "world"], ["good", "lord"], ["hello", "lord"]]
result = Hash.new{|k,v| k[v] = []}
a.each_with_index{|b,i| b.each{|c| result[c] << i} }
result
#=> {"good"=>[1], "world"=>[0], "lord"=>[1, 2], "hello"=>[0, 2]}

Upvotes: 1

Wayne Conrad
Wayne Conrad

Reputation: 108179

Just for grins, a functional solution:

#!/usr/bin/ruby1.8

a = [["hello", "world"], ["good", "lord"], ["hello", "lord"]]

b = a.flatten.uniq.inject({}) do |hash, word|
  hash.merge(word => a.each_with_index.collect do |list, i|
               list.index(word) && i
             end.compact)
end

p b    # => {"world"=>[0], "good"=>[1], "lord"=>[1, 2], "hello"=>[0, 2]}

Upvotes: 1

Marc-Andr&#233; Lafortune
Marc-Andr&#233; Lafortune

Reputation: 79612

Slight improvement (imho) on vava's solution:

tokens = [["hello", "world"], ["good", "lord"], ["hello", "lord"]]

tokens_hash = Hash.new{|h, k| h[k] = []}

tokens.each_with_index do |subarr, i|
  subarr.each do |word|
    tokens_hash[word] << i
  end
end

Upvotes: 4

vava
vava

Reputation: 25401

tokens = [["hello", "world"], ["good", "lord"], ["hello", "lord"]]

tokens_hash = Hash.new([])

tokens.each_with_index do |subarr, i|
    subarr.each do |word|
        tokens_hash[word] = tokens_hash[word] + [i]
    end
end

p tokens_hash #=>{"good"=>[1], "world"=>[0], "lord"=>[1, 2], "hello"=>[0, 2]}

My solution will scan the whole structure just once.

Upvotes: 1

Tuomas Pelkonen
Tuomas Pelkonen

Reputation: 7831

ret = []
a.each_with_index {|x, i| if x.include?(keyword) then ret << i end }

Upvotes: 2

Related Questions