-2

Having the array "a" I want to look for a pair of values within array "a". "02" followed by "10" and if found, I want to create 2 new arrays, one beginning in "02", "10" and the other beginning 3 positions after "02", "10".

a = ["11", "45", "01", "01", "02", "00", "10", "4C", "02", "10", "00", "42", "00", "00", "26"]

If I look the index of 02 and 10 individually I get 4 and 6 respectively, but index of the pair "02", "10" is 8.

irb(main)> a.index("02")
=> 4
irb(main)> a.index("10")
=> 6

The desired output would be like this:

b = ["02", "10", "00", "42", "00", "00", "26"]

c = ["00", "00", "26"]

How can I do this?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Ger Cas
  • 2,188
  • 2
  • 18
  • 45
  • Presumably you want to find the index of the first `"02"` that is immediately followed by `"10"`. If so you should just say that and not mention the indices of the preceeding `"02"` and `"10"` that are not adjacent, which just confuses the question. Also, "...beginning 3 positions after '02', '10'". would be clearer if you said '...after "10"'. – Cary Swoveland Feb 03 '19 at 07:25
  • I mention the indices of `"02"` and `"10"` individually to show that if there are several `"02"` and `"10"` before the pair `"02", "10"` then the resulting index would be incorrect. And saying 3 positions after `"02", "10"` is to emphasize that is after the pair, because there are more than one `"10"` – Ger Cas Feb 03 '19 at 08:25
  • 1
    Are the values in your array hex strings representing binary data? If so, it might be easier to convert the array into a binary string (e.g. `str = [a.join].pack('H*')`) and use string methods to find the index (e.g. `str.index("\x02\x10") #=> 8`) or a regular expression to extract the data. – Stefan Feb 04 '19 at 09:53
  • Hi Stefan. Your solution it works pretty fine too and even shorter. Thanks for your help – Ger Cas Feb 05 '19 at 04:40

2 Answers2

2
def find_em(a)
  i = (a.size-1).times.find { |i| [a[i], a[i+1]] == ["02", "10"] }
  i.nil? ? nil : [a[i..-1], a[i+4..-1] || []]
end

find_em(a)
  #=> [["02", "10", "00", "42", "00", "00", "26"], ["00", "00", "26"]] 

find_em ["10", "4C", "02", "10", "00", "42"]
  #=> [["02", "10", "00", "42"], []] 

find_em ["10", "4C", "02", "10"]
  #=> [["02", "10"], []] 

find_em ["10", "4C", "10", "00", "42"]
  #=> nil 

find_em []
  #=> nil 
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
1

To let it work with more occurrence of ["02", "10"], conditional stolen from @Cary Swoveland answer :)

def split_strange(ary)
  res = []
  (ary.size - 1).times do |i|
    res << [ary[i..-1], ary[i+4..-1]] if [ary[i], ary[i+1]] == ["02", "10"]
  end
  return res.flatten(1) # or whathever
end

So, it can handle also:

k = ["02", "10", "02", "10", "00", "42", "00", "00", "26"]
split_strange(k)
#=> [["02", "10", "02", "10", "00", "42", "00", "00", "26"], ["00", "42", "00", "00", "26"], ["02", "10", "00", "42", "00", "00", "26"], ["00", "00", "26"]]


Alternative, but works with one occurrence:
def split_strange_2(ary)
  tmp = ary.slice_when { |a, b|  a == "02" and b == "10" }.to_a
  res = tmp.last.unshift tmp.first.last
  return res, res[4..-1] || [] if tmp.size == 2
end

split_strange_2(a)
#=> [["02", "10", "00", "42", "00", "00", "26"], ["00", "00", "26"]]
iGian
  • 11,023
  • 3
  • 21
  • 36
  • IGian, thanks for your help and for a new solution to handle more occurrences. Always great to see more ways to do the same thing to learn from those you knows much more – Ger Cas Feb 03 '19 at 08:34