Reputation: 1127
I have the following 2 dimension array
data = [
[5014031, nil], [5014032, nil], [5014033, 0],
[5014034, nil], [3014035, 1], [5014036, 1],
[5014037, 2], [5014038, nil], [5014039, 2],
[5014040, nil], [2014041, nil], [3014042, 2]
]
When I know the value of the 1st integer of one of these arrays e.g. 5014034, what would be the most efficient way to gain the next integer value where the 2nd element matches to nil? (e.g. I would expect 5014038 to be returned)
Thanks Scott
Upvotes: 1
Views: 54
Reputation: 36536
Simple way, using #drop_while
and #find_index
:
data = [
[5014031, nil], [5014032, nil], [5014033, 0],
[5014034, nil], [5014035, 1 ], [5014036, 1],
[5014037, 2 ], [5014038, nil], [5014039, 2],
[5014040, nil], [5014041, nil], [5014042, 2]
]
remaining_arr = data.drop_while { |arr| arr[0] != 5014034 }[1..]
next_int = remaining_arr[remaining_arr.find_index { |arr| arr[1].nil? }][0]
Alternatively:
data
.drop_while { |x| x[0] != 5014034 }[1..]
.drop_while { |x| !x[1].nil? }[0][0]
# => 5014038
Upvotes: 3
Reputation: 33420
You could slice the array into two when the first element in the inner array matches 5014034
. Extract the second resulting array and use find to look for the inner array whose second element is nil:
arr
.slice_when { |a, _| a == 5014034 } # #<Enumerator: ...>
.to_a # [[[5014031, nil], [5014032, nil], [5014033, 0], [5014034, nil]], [[5014035, 1], [5014036, 1], [5014037, 2], [5014038, nil], [5014039, 2], [5014040, nil], [5014041, nil], [5014042, 2]]]
[1] # [[5014035, 1], [5014036, 1], [5014037, 2], [5014038, nil], [5014039, 2], [5014040, nil], [5014041, nil], [5014042, 2]]
.find { |_, b| b.nil? } # [5014038, nil]
[0] # 5014038
Notice this method chaining might fail if there's no array in arr whose first object inside matches 5014034
, and/or the same for find
.
Upvotes: 2
Reputation: 26353
If sorted then the following might be faster
data = [
[5014031, nil], [5014032, nil], [5014033, 0],
[5014034, nil], [5014035, 1], [5014036, 1],
[5014037, 2], [5014038, nil], [5014039, 2],
[5014040, nil], [5014041, nil], [5014042, 2]
]
start_element = data.bsearch_index{ |a| a[0] >= 5014034 }
if start_element == nil || data[start_element] != 5014034
puts "not found"
else
data.slice((start_element+1)..).find { |a| a[1] == nil }[0]
end
Upvotes: 0