I am just trying to understand javascript as I am a bit new to it and its such a power-full language.

I wanted to know how to re-arrange words and numbers in a string so some words can always be in the front. So in this case the number and measurement will always be in front of the value.

For example the desired output from input:

Function input: Wood Plank 1 cm
Function output: 1 cm Wood Plank

Function input: Lawn Mower 1
Function output: 1 Lawn Mower

Function input: Tape Measure
Function output: Tape Measure

I have this regex that I made which works but I need to know how to apply it

const unitCapturingRegX = (/^(?<amount>¼|½|¾|\d+\/\d+|\d+)\s*(?<value>.*)$/);

I have got some measurements below:

const measures = [
  "cm", "m", "kg", "kgs", "kilogram", "kilograms", "l", "liter" ,"tbs","meter", "inch",
];

This is my input Values:

const inputVal = [
  'Tape 1/2 cm',
  '1kg cement',
  '3 l water',
  'carbon fibre ½ inch'
]

Is this a possible thing to do , please can someone help me!!!

2

There are 2 best solutions below

6
On BEST ANSWER

Add the units to the end of the regualr expression

var re = /(.*)\s(¼|½|¾|\d+\/\d+|\d+)\s?(cm|m|kg|kgs|kilogram|kilograms|l|liter|tbs|meter|inch)?$/;

const inputVal = [
  'Tape 1/2 cm',
  'cement 1kg',
  '1kg cement',
  '3 l water',
  'water 3 l',
  'carbon fibre ½ inch',
  'Lawn Mower 1'
]

const altered = inputVal.map(function(str) {
  return str.replace(re, "$2 $3 $1") // or "$2$3 $1"
})

console.log(altered);

And generating it from the array

const measures = [
  "cm", "m", "kg", "kgs", "kilogram", "kilograms", "l", "liter" ,"tbs","meter", "inch",
];

var units = measures.join("|");
var re = new RegExp("(.*)\\s(¼|½|¾|\\d+\\/\\d+|\\d+)\\s?(" + units + ")?$");

const inputVal = [
  'Tape 1/2 cm',
  'cement 1kg',
  '1kg cement',
  '3 l water',
  'water 3 l',
  'carbon fibre ½ inch'
]

const altered = inputVal.map(function(str) {
  return str.replace(re, "$2 $3 $1") // or "$2$3 $1"
})

console.log(altered);

0
On

The provided approach is based on this regex (/^(?<left>[^¼½¾\d]+)*(?<count>¼|½|¾|\d+\/\d+|\d+)\s*(?<unit>kilograms|l|cm|m)*(?<right>.*)/). There it is described in detail.

The regex takes optional matter/material <left> and/or <right> from a measure into account. A measure again is composed of a valid number- or fraction-<count> and an optional <unit>.

Any string value can be passed to a sanitizer function which uses its main replace method for rearranging the capture groups by a replacement function. The second replace step applies also to string values that did not match the regex.

Thus, with all these steps, one assures pretty clean results regardless of the quality of the input data ...

const regXMeasureAndMatter = (/^(?<left>[^¼½¾\d]+)*(?<count>¼|½|¾|\d+\/\d+|\d+)\s*(?<unit>kilograms|kilogram|kgs|kg|liter|l|tbs|inch|meter|cm|m)*(?<right>.*)/);

function rearrangeMeasureAndMatter(match, left, count, unit, right) {
  left = (left || '' ).trim();
  right = (right || '' ).trim();
  return [
  
    count,
    (unit || ''),
    [left, right].join((left && right && ', ') || '')

  ].join(' ')
}
function sanitizeMeasureAndMatter(str) {
  return str
    .replace(regXMeasureAndMatter, rearrangeMeasureAndMatter)
    .replace(/\s+/g, ' ').trim()
}
console.log([

  '  left   22/33   kilogram   right  ',
  '     Tape Measure     ',
  '21m  Wood Plank',
  '  3l Wood   Plank  ',
  ' Wood  Plank  20/10  cm ',
  'Lawn Mower 2/2',
  'Tape   123   Measure',
  '  Wood Plank   ½    cm  ',
  'Lawn   Mower ¾  cm',
  '  Tape     Measure  ',
  '  safas 1/2  '

].map(sanitizeMeasureAndMatter));
.as-console-wrapper { min-height: 100%!important; top: 0; }

A solution that generates the regex on the fly based by a unit array follows the above approach and just changes the way of how a regex is created ...

const unitList = ['kilograms', 'kilogram', 'kgs', 'kg', 'liter', 'l', 'tbs', 'inch', 'meter', 'cm', 'm'];

const regXMeasureAndMatter = RegExp('^(?<left>[^¼½¾\\d]+)*(?<count>¼|½|¾|\\d+\\/\\d+|\\d+)\\s*(?<unit>' + unitList.join('|') + ')*(?<right>.*)');

function rearrangeMeasureAndMatter(match, left, count, unit, right) {
  left = (left || '' ).trim();
  right = (right || '' ).trim();
  return [
  
    count,
    (unit || ''),
    [left, right].join((left && right && ', ') || '')

  ].join(' ')
}
function sanitizeMeasureAndMatter(str) {
  return str
    .replace(regXMeasureAndMatter, rearrangeMeasureAndMatter)
    .replace(/\s+/g, ' ').trim()
}
console.log([

  '  left   22/33   kilogram   right  ',
  '     Tape Measure     ',
  '21m  Wood Plank',
  '  3l Wood   Plank  ',
  ' Wood  Plank  20/10  cm ',
  'Lawn Mower 2/2',
  'Tape   123   Measure',
  '  Wood Plank   ½    cm  ',
  'Lawn   Mower ¾  cm',
  '  Tape     Measure  ',
  '  safas 1/2  '

].map(sanitizeMeasureAndMatter));
.as-console-wrapper { min-height: 100%!important; top: 0; }