Ranges in ruby are pretty cool. I end up with arrays such as this:
geneRanges = [(234..25), (500..510), (1640..1653)]
And subsequently have to remove bits of them. For that I:
genePositions = geneRanges.collect {|range| range.entries }.flatten
=> [500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653]
They get manipulated, so some numbers get excluded, and others may be added. I may end up with this:
[505, 506, 507, 600, 601, 602, 603, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654]
How can I convert this back into a compact array of ranges? It seems that the inverse function should exist? I would expect it to return something like this:
[(505..507), (600..603), (1643..1654)]
Thanks!
The elements of array InputData are INTEGERs and the indices are in the range of 0 and 100.
The index indicates the position of the element within the array (starting from 1) and is either a number or a field containing a number. The following rules apply when you specify an array name and index: The array name must be a unique symbolic name.
Array Indexing means searching for elements in an array using the index (position) of elements for quick retrieval of information.
To select an element from Numpy Array , we can use [] operator i.e. It will return the element at given index only.
(New and improved. Stays fresh in your refrigerator for up to two weeks!):
a = [1, 2, 3, 10, 11, 20, 20, 4]
ranges = a.sort.uniq.inject([]) do |spans, n|
if spans.empty? || spans.last.last != n - 1
spans + [n..n]
else
spans[0..-2] + [spans.last.first..n]
end
end
p ranges # [1..4, 10..11, 20..20]
Functional, not-very-readable solution:
(a[0,1]+a.each_cons(2).reject{|i,j| j-i==1}.flatten+a[-1,1]).
each_slice(2).map{|i,j| i..j}
And a nice one:
class Array
# splits array to sub-arrays wherever two adjacent elements satisfy a condition
def split_by
each_cons(2).inject([[first]]){|a, (i, j)|
a.push([]) if yield(i, j)
a.last.push j
a
}
end
# uses split_by to split array to subarrays with consecutive elements, then convert to range
def to_range
split_by{|i,j| j-i!=1}.map{|a| a.first..a.last}
end
end
[505, 506, 507, 600, 1647, 1648, 1649, 1650, 1651, 1654].split_by{|i,j| j-i!=1}
#=> [[505, 506, 507], [600], [1647, 1648, 1649, 1650, 1651], [1654]]
[505, 506, 507, 600, 1647, 1648, 1649, 1650, 1651, 1654].to_range
#=> [505..507, 600..600, 1647..1651, 1654..1654]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With