У меня есть этот ввод-
"\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?"
Я хочу этот вывод-
[
"What makes Vue a popular choice for web development?",
"How does Vue compare to other JavaScript frameworks?",
"What are the advantages of using Vue?",
"Does Vue support server-side rendering?",
"Is Vue compatible with TypeScript?",
"Does Vue have a built-in router?",
]
Я пробовал это-
let string = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?"
// First, remove all line breaks and two strings
string = string.replace(/(\r\n|\n|\r)/gm, "").replace('Open Ended Questions:', '').replace('Closed Ended Questions:', '');
// Split the string from this format, "<integer><dot><space>"
let result = string.split(/(\d+)\.\ /);
// Filter the only items which are not empty and not a number
result = result.filter(item => item && isNaN(item));
// Final result
console.info(result);
Объяснение кода-.
<integer><dot><space>
, т.е. "1. ", "2. "
и т.д.Решение работает нормально, но я не уверен, что это правильный способ сделать это из-за этой жестко запрограммированной операции удаления - replace('Open Ended Questions:', '').replace('Closed Ended Questions:', '')
Может ли кто-нибудь предложить лучший/несложный/правильный способ сделать это?
Звучит достаточно хорошо, я не думаю, что вы все равно можете оптимизировать его с точки зрения производительности/удобочитаемости. Оставь как есть, отлично!
Спасибо, @Fractalism. Ваша точка зрения верна, мое решение не сработает в этом случае подстроки.
const input = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?"
const lines = input.split('\n');
const listItems = lines
.filter((line) => /^\d+\./.test(line))
.map((line) => line.replace(/^\d+\./, "").trim());
console.info(listItems);
Некоторые предложения: 1. (\d+)
не нужны круглые скобки (хотя, если они там для удобочитаемости, тогда все в порядке) 2. .
должен быть \.
, чтобы соответствовать буквальному символу точки 3. Символ пробела можно заменить на \s+
, чтобы соответствовать нескольким последовательным пространства
Перебрать строки из ввода и, если строка соответствует /^\d+\.\s+
(то есть цифрам-точкам-пробелам), поместить оставшуюся часть строки в массив:
input = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?"
output = []
for (let line of input.split('\n')) {
line = line.trim()
let m = line.match(/^\d+\.\s+(.+)/)
if (m)
output.push(m[1])
}
console.info(output)
Вы также можете сделать это с помощью одного регулярного выражения, но это будет менее читаемо IMO:
input = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?"
output = [...input.matchAll(/^\d+\.\s+(.+)/gm)].map(r => r[1])
console.info(output)
Если вы разделите новую строку, вы получите
part 0:
part 1:
part 2: Open Ended Questions:
part 3: 1. What makes Vue a popular choice for web development?
part 4: 2. How does Vue compare to other JavaScript frameworks?
part 5: 3. What are the advantages of using Vue?
part 6:
part 7: Closed Ended Questions:
part 8: 1. Does Vue support server-side rendering?
part 9: 2. Is Vue compatible with TypeScript?
part 10: 3. Does Vue have a built-in router?
Затем вы можете отфильтровать пустые и нерелевантные строки.
Затем удалите цифры в начале.
Использование положительного просмотра назад (?<=)
и просмотра вперед (?=)
:
const str = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?";
const items = str.match(/(?<=^\d+\. +).+?(?=\n|$)/gm)
console.info(items);
Пояснение к: Regex101.com
(?<=\n\d+\. +)
Начало строки, одна или несколько цифр, точка, один или несколько пробелов.+?
любой символ один или несколько раз как можно меньше(?=\n|$)
новая строка или конец строкииспользуйте это упрощенное регулярное выражение, которое в основном соответствует началу строки ^
, имеющему цифру / с, за которыми следует шаблон точки и пробела, и захватывает оставшуюся строку (.+)
до конца строки $
(с глобальными и многострочными флагами gm
)
/^\d\. (.+)$/gm
Демонстрация Regex101.com и объяснение
Для поддержки браузеров на основе WebKit, таких как Safari, которые не поддерживают утверждение Lookbehind, вы можете использовать String.prototype.matchAll() , чтобы получить итератор с совпавшими группами. Используйте синтаксис распространения ...
, чтобы получить 2D-массив и получить доступ к первой соответствующей группе, используя match[1]
, и преобразовать его в массив, используя Array.ptototype.map()
const str = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?";
const items = [...str.matchAll(/^\d\. (.+)$/gm)].map(m => m[1]);
console.info(items);
Для дополнительной поддержки старых браузеров Internet Explorer, которые не поддерживают метод String.prototype.matchAll(), используйте .exec()
, например:
const str = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?";
const reg = /^\d\. (.+)$/gm;
const res = [];
let m;
while(m = reg.exec(str)) res.push(m[1]);
console.info(res);
Спасибо, @Roko, это самое простое решение. Единственная проблема в том, что я прочитал об этих операторах и обнаружил, что оператор lookbehind
не поддерживается в браузерах, отличных от V8, таких как Safari и Internet Explorer, и этот ответ также не работает в Safari. У вас есть какие-нибудь мысли по этому поводу?
Это зависит от вашего ввода, и всегда ли вопрос имеет одинаковую структуру? Если да, вам нужно определить регулярное выражение, соответствующее формату ваших вопросов, и оттуда вам не нужно ничего заменять предложениями с пустыми строками:
let string = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?"
// ([0-9])+ is the question number and it has to be 1 or more than one character
// \. is the dot after question number
// .+ is your question
// (\?)? the first question mark after the question text
let regexp = /([0-9])+\..+(\?)?/g;
var questions = string.match(regexp);
var result = [];
questions.forEach((l) => result.push(l.replace(/([0-9])+\./g,'').trim()));
console.info(result);
Я предполагаю, что каждый вопрос заканчивается на ?
и начинается с новой строки \n
в соответствии с указанной вами входной строкой. Принимая во внимание приведенный выше шаблон, вот обходное решение для достижения требуемого результата.
// Input string
const str = "\n\nOpen Ended Questions:\n1. What makes Vue a popular choice for web development?\n2. How does Vue compare to other JavaScript frameworks?\n3. What are the advantages of using Vue?\n\nClosed Ended Questions:\n1. Does Vue support server-side rendering?\n2. Is Vue compatible with TypeScript?\n3. Does Vue have a built-in router?";
// Splitted the input string based on the new line character '\n'
const splittedStr = str.split("\n");
// Filtered out the array items which ends with question mark (?)
const questionsArr = splittedStr.filter(str => str.endsWith('?'));
// Finally removing the numbers from the starting of the question texts.
const res = questionsArr.map(str => str.replace(/^[\d]+\.\ /, ''));
// Desired output
console.info(res);
Я бы сначала разделил на разрывы строк, а затем обработал бы каждый вопрос. То, как вы это делаете, может привести к ошибке, если один из этих вопросов содержит подстроку формы
<integer><dot><space>
(например, ссылка на предыдущий вопрос).