If I have a sorted array, how do I find the sequential numbers? Btw, this is for determining if a poker hand is a straight or not. Duplicates in the array have been removed. I can do this, but it would be a multi-line method and I thought开发者_JAVA百科 there might be a quick one liner using an Enumerable method.
For example:
FindSequence([9,8,7,5,4]) = [9,8,7]
FindSequence([4,2,0]) = nil
In 1.9.2, a mysterious slice_before method was added to Enumerable. You can utilize it:
def find_sequences_desc(a)
prev = a[0]
a.slice_before { |cur|
prev, prev2 = cur, prev # one step further
prev2 - 1 != prev # two ago != one ago ? --> new slice
}.to_a
end
# find_sequences_desc [9,8,7,4,4] #=> [[9, 8, 7], [4], [4]]
# find_sequences_desc [9,8,7,5,4] #=> [[9, 8, 7], [5, 4]]
def find_sequences_asc(a)
prev = a[0]
a.slice_before { |cur|
prev, prev2 = cur, prev # one step further
prev2 + 1 != prev # two ago != one ago ? --> new slice
}.to_a
end
# find_sequences_asc [1,2,4,5,7] #=> [[1, 2], [4,5], [7]]
# find_sequences_asc [1,2,3,5,6] #=> [[1, 2, 3], [5, 6]]
You can get the semantics you need with
def find_longest_sequence(a)
s = find_sequences_desc(a).max
s unless s.size <= 1
end
Update
Ruby 2.2 adds a slice_when method, which simplifies the code a lot:
def find_sequences_desc(a)
a.slice_when { |prev, cur|
cur != prev - 1
}.to_a
end
# find_sequences_desc [9,8,7,4,4] #=> [[9, 8, 7], [4], [4]]
# find_sequences_desc [9,8,7,5,4] #=> [[9, 8, 7], [5, 4]]
Assuming it is presorted, you can easily test for a straight like so:
array.each_cons(2).all? { |x,y| y == x - 1 }
To be safe you may want to add the sort:
array.sort.each_cons(2).all? { |x,y| y == x + 1 }
But if you really need to extract the largest sequence, it will take another solution.
If as you say you've sorted and removed duplicates, then the array is in sequence if the difference between the first and last elements of the array equals the difference in their indices. (I'm being vague here because I believe my answer can be generalised.)
精彩评论