Хорошо, банда, вот моя загадка:
Я ищу соответствие строки, используя ванильный JavaScript test()
, функцию прототипа RegExp
, для проверки входной переменной inp
:
/{CONDITION}/.test(inp)
Строка должна удовлетворять следующим условиям:
Длина может быть один или два символа.Достаточно просто.
/^*{1,2}$/.test(inp)
Это должно быть без учета регистра.Нет проблем.
/^*{1,2}$/i.test(inp)
Если только один символ, он должен состоять из только символов [tmbrcl]
/^[tmblcr]{1}$/i.test(inp)
Если длина двухсимвольная, первый символ должен быть [tmb]
ИЛИ [lcr]
, а второй должен быть в зависимости от того, какое из первых значений установлено , а не .Хорошо:
/^([tmblcr]{1})$|^([tmb]{1}[lcr]{1})|^([lcr]{1}[tmb]{1})$/i.test(inp)
Примеры:
't' // Good
'B' // Good
'Rc' // Good
'bl' // Good
'tb' // bad
'mm' // Bad
'cC' // Bad
'BB' // Bad
'Bob' // Bad
'5' // Bad
'Ċ' // Still Bad
'ß' // Suspiciously Bad
'?' // Now you're just screwing with me
'上' // You know what? I don't care if this fails gracefully or not. ^&%* you.
Моя цель здесь - проанализировать пользовательский ввод, который укажет вертикальное и горизонтальное положение ('T'/'M'/'B'
представляет'Top'/'Middle'/'Bottom'
и 'L'/'C'/'R'
, представляющие 'Left'/'Center'/'Right'
соответственно).Пользователю должно быть разрешено передавать любую перестановку двух группировок, в любом случае, в любом порядке (или только одну, в этом случае другой выводится как значение по умолчанию).
I'mне зациклен на использовании регулярных выражений, но казалось неуклюжим делать что-то вроде (или столь же глупо):
let errd = false;
set1 = 'TMB',
set2 = 'LCR',
sets = set1 + set2;
if(inp.length === 1 && sets.indexOf(inp) === -1) errd = true;
else if(inp.length === 2){
let inpArr = inp.split('');
errd = (set1.indexOf(inpArr[0]) === set1.indexOf(inpArr[1]) === -1 || set2.indexOf(inpArr[0]) === set2.indexOf(inpArr[1]) === -1);
}else errd = true;
Поэтому мой вопрос: Неужели нет более изящного способа справиться с этим, чем простовыплевывая каждую перестановку желаемого результата?
/^[SINGLE (S)]$|^[CASE A/B]$|^[CASE B/A]$/i
Я имею в виду, что если бы было три,
/^[S]$|^[AB]$|^[AC]$|^[BC]$|^[BA]$|^[CA]$|^[CB]$|^[ABC]$|^[ACB]$|^[BAC]$|^[BCA]$|^[CAB]$|^[CBA]$/i
или (боги помогают мне), ЧЕТЫРЕ персонажа с подобным набором ограничений?Я относительно новичок в RegEx, и мне интересно, не хватает ли здесь основного принципа.У меня есть рабочее решение (версия "/^[S]|[AB]|[BA]$/
"), но действительно ли это ПРАВИЛЬНОЕ?
РЕДАКТИРОВАТЬ
Спасибо за звездный, исчерпывающий ответ, Sweeper!
(Вот рабочий код в контексте, на случай, если он позже кому-нибудь поможет):
orient: function(objQS, rPos='TL', offsetWidth=0, offsetHeight=0) {
try{
// objQS accepts a QuerySelector string or an HTMLElement
let obj = (typeof(objQS) === 'string') ? document.querySelector(objQS) : objQS;
console.log('obj', obj, obj.getBoundingClientRect())
if(null == obj || typeof(obj) !== 'object'){ throw('Invalid Target!'); }
let objBRC = obj.getBoundingClientRect();
// rPos accepts TL, T/TC, TR, ML, M/C/MC, MR, BL, B/BC, BR (case- and order-insensitive)
if(!/^(?:[tmbrcl]|[tmb][rcl]|[rcl][tmb])$/i.test(rPos)){ throw('Invalid orientation specified!'); }
// Accomodate single-character entry of 'm' or 'c', both taken to mean 'mc' ('m'iddle-'c'enter)
if(/^[mc]$/i.test(rPos)) { rPos = 'mc'; }
// Set default orientation to top-left (tl/lt), meaning we have nothing to do for 't'op or 'l'eft
let osT = objBRC.y + offsetHeight, // Note we add the user-set offsets to our bases
osL = objBRC.x + offsetWidth; // so they carry though to the other options.
if(/m/i.test(rPos)) { osT += (objBRC.height / 2); } // Adjust vertically for 'm'iddle (top + height/2)
if(/b/i.test(rPos)) { osT += objBRC.height; } // Adjust vertically for 'b'ottom (top + height)
if(/c/i.test(rPos)) { osL += (objBRC.width / 2); } // Adjust horizontally for 'c'enter (left + width/2)
if(/r/i.test(rPos)) { osL += objBRC.width; } // Adjust horizontally for 'r'ight (left + width)
objBRC.offsetTop = osT;
objBRC.offsetLeft = osL;
this.place(osL, osT);
console.log('return', 'objBRC:', objBRC)
return objBRC;
}catch(e){
console.group('ERROR DETAILS (Error in callout.orient)');
console.error('Error details:\n - ', e);
console.groupEnd();
return false;
}
}