0

I wrote a simple function to replace some strings.

Rules:

  • Every dot must be replaced by "_attributes.";
  • Every [numbers] must be replaced by .numbers; (numbers means 1, 123... and so on)

Actually I wrote the replace like this:

str.replace(/(\[?\d*\]?\.)/g, '_attributes$1')
   .replace(/\[(\d+)\]/g, '.$1');

Input examples:

model.city
model[0].city
model0.city
model[0].another_model[4].city

Expected output:

model_attributes.city
model_attributes.0.city
model0_attributes.city
model_attributes.0.another_model_attributes.4.city

It's almost done, except that it fails for the case that I have a number (without brackets) before a dot like this:

model0.city

It prints:

model_attributes0.city

While I expect it to be:

model0_attributes.city

Below is a simple snippet that you play and see what I'm trying to achieve:

var fields = [
  'model.city', 
  'model[0].city', 
  'model0.city', 
  'model[0].another_model[4].city',
  'model[0].another_model4.city'
];

var expectedArr = [
  'model_attributes.city',
  'model_attributes.0.city',
  'model0_attributes.city',
  'model_attributes.0.another_model_attributes.4.city',
  'model_attributes.0.another_model4_attributes.city'
];

var replacedArr = [];
for (const field of fields) {
  var replaced = field.replace(/(\[?\d*\]?\.)/g, '_attributes$1').replace(/\[(\d+)\]/g, '.$1');
  replacedArr.push(replaced);
}

console.log('expected => ', expectedArr);
console.log('actual => ', replacedArr);

What I have to change in my replace function to make it work? TIA.

2 Answers 2

1

In the first regex, just make a cluster group optional, like this

str.replace(/((?:\[\d+\])?\.)/g, '_attributes$1')

and you're good to go.

Expanded

 (                             # (1 start)
      (?: \[ \d+ \] )?              # Optional '[ddd]' group
      \.                            # Required dot
 )                             # (1 end)

JS sample

function PrintMod( str )
{
    console.log( str.replace(/((?:\[\d+\])?\.)/g, '_attributes$1')
       .replace(/\[(\d+)\]/g, '.$1') );
}

PrintMod( 'model.city' );
PrintMod( 'model[0].city' );
PrintMod( 'model0.city' );
PrintMod( 'model[0].another_model[4].city' );
PrintMod( 'model[0].another_model4.city' );

Sign up to request clarification or add additional context in comments.

Comments

1

This should be what you're looking for:

var fields = [
  'model.city', 
  'model[0].city', 
  'model0.city', 
  'model[0].another_model[4].city',
  'model[0].another_model4.city'
];

var expectedArr = [
  'model_attributes.city',
  'model_attributes.0.city',
  'model0_attributes.city',
  'model_attributes.0.another_model_attributes.4.city',
  'model_attributes.0.another_model4_attributes.city'
];

var replacedArr = [];
for (const field of fields) {
  var replaced = field.replace(/(\[\d+\])?\./g, '_attributes$1.').replace(/\[(\d+)\]/g, '.$1');
  replacedArr.push(replaced);
}

console.log('expected => ', expectedArr);
console.log('actual => ', replacedArr);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.