0

I would like to replace the captured group of a string with the elements of an array.

I am trying something like this:

part_number = 'R1L16SB#AA'
regex = (/\A(RM|R1)([A-Z])(\d\d+)([A-Z]+)#?([A-Z])([A-Z])\z/)
g = ["X","Y","Z"]
g.each do |i|
  ren_m,ch_conf,bit_conf,package_type,packing_val,envo_vals = part_number.match(regex).captures
  m = part_number.sub! packing_val,i
  puts m
end

My code with array g = ["X","Y","Z"] is giving desired output as:

R1L16SB#XA
R1L16SB#YA
R1L16SB#ZA

The captured group packing_val is replaced with

g = ["X","Y","Z"]

But when the array has elements which are already present in the string then it is not working:

g = ["A","B","C"]

outputs:

R1L16SB#AA
R1L16SB#BA
R1L16SC#BA 

But my expected output is:

R1L16SB#AA
R1L16SB#BA
R1L16SB#CA

What is going wrong and what could be the possible solution?

code_t
  • 49
  • 8

2 Answers2

1

sub! will replace the first match every iteration on part_number which is outside of the loop.

What happens is:

In the first iteration, the first A will be replaced with A giving the same

R1L16SB#AA
        ^

In the second iteration, the first A will be replaced by B giving

R1L16SB#BA
        ^   

In the third iteration, the first B will be replaced by C giving

R1L16SC#BA
      ^

One way to get the desired output is to put part_number = 'R1L16SB#AA' inside the loop.

Ruby demo

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
The fourth bird
  • 154,723
  • 16
  • 55
  • 70
  • @The fourth bird Thanks ! Is there a way where I don't need to capture the position all over again for new array elements,once I capture the position of 'packing_val' it can replaced with ["A","B","C"] directly ? as of now I am matching the string with regex and capturing the position for all the array elements. – code_t Nov 11 '19 at 09:58
  • @code_t The current answers are for the original question. Instead of modifying the question, you could always ask a new one. Perhaps [this page](https://stackoverflow.com/questions/5241653/ruby-regex-match-and-get-positions-of) or [this page](https://stackoverflow.com/questions/4274388/how-to-get-indexes-of-all-occurrences-of-a-pattern-in-a-string) can be helpful. – The fourth bird Nov 11 '19 at 10:23
  • 1
    Thanks! I have removed the new query from this question – code_t Nov 11 '19 at 10:27
1

You mutated your part_number every iteration. That's the reason.

Just switch to sub without bang:

m = part_number.sub(packing_val, i)

You can do it without regex:

part_number = 'R1L16SB#AA'

g = %w[X Y Z]

g.each do |i|
  pn = part_number.dup
  pn[-2] = i
  puts pn
end
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
mechnicov
  • 12,025
  • 4
  • 33
  • 56
  • Thanks ! Is there a way where I don't need to capture the position all over again for new array elements,once I capture the position of 'packing_val' it can replaced with ["A","B","C"] directly ? as of now I am matching the string with regex and capturing the position for all the array elements. – code_t Nov 11 '19 at 09:59