views:

184

answers:

6

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 
+2  A: 
ret = []
a.each_with_index {|x, i| if x.include?(keyword) then ret << i end }
Tuomas Pelkonen
this is much faster.
j.
What's `keyword`?
Mladen Jablanović
I suppose `keyword` can be `"hello"`, `"world"`, `"good"` and `"lord"`.
j.
So this is an update of the part of the code from the question? Wouldn't be useful to have quoted complete working snippet here then?
Mladen Jablanović
generally it is not working solution. firstly keyword is not defined, secondly, even if we will define keyword `ret` will return array of numbers, not hash that is the goal
fl00r
+1  A: 
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.

vava
+2  A: 
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]}
Mladen Jablanović
you can't use `each_with_index` without block
fl00r
I can, in Ruby >= 1.8.7. It's returning `Enumerator` instance.
Mladen Jablanović
oh, sorry. I still use 1.8.6
fl00r
(acc[e] ||= []) << i :)
vava
+3  A: 

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
Marc-André Lafortune
actually, looks like this is the faster method...
j.
I've suggested same solution :)
fl00r
+1  A: 

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]}
Wayne Conrad
+1  A: 
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]}
fl00r