Reputation: 426
I want to get the coordinates of every occurrence of an object stored in an array of arrays. If I have an array:
array = [["foo", "bar", "lobster"], ["camel", "trombone", "foo"]]
and an object "foo"
, I want to get:
[[0,0], [1,2]]
The following will do this, but it's elaborate and ugly:
array.map
.with_index{
|row,row_index| row.map.with_index {
|v,col_index| v=="foo" ? [row_index,col_index] : v
}
}
.flatten(1).find_all {|x| x.class==Array}
Is there a more straightforward way to do this? This was asked before, and produced a similarly inelegant solution.
Upvotes: 1
Views: 516
Reputation: 110745
Another way:
array = [["foo", "bar", "lobster"], ["camel", "trombone", "foo"],
["goat", "car", "hog"], ["foo", "harp", "foo"]]
array.each_with_index.with_object([]) { |(a,i),b|
a.each_with_index { |s,j| b << [i,j] if s == "foo" } }
#=> [[0,0], [1,2], [3,0], [3,2]
Upvotes: 2
Reputation: 168239
It's better to work with flat arrays.
cycle = array.first.length
#=> 3
array.flatten.to_enum.with_index
.select{|e, i| e == "foo"}
.map{|e, i| i.divmod(cycle)}
#=> [[0, 0], [1, 2]]
or
cycle = array.first.length
#=> 3
array = array.flatten
array.each_index.select{|i| array[i] == "foo"}.map{|e, i| i.divmod(cycle)}
#=> [[0, 0], [1, 2]]
Upvotes: 0
Reputation: 59343
Here's a slightly more elegant solution. I have:
flat_map
instead of flatten
ing at the end.each_index.select
instead of .map.with_index
and then having to strip non-arrays at the end, which is really uglyarray.flat_map.with_index {|row, row_idx|
row.each_index.select{|i| row[i] == 'foo' }.map{|col_idx| [row_idx, col_idx] }
}
Upvotes: 4