Найти последовательности между двумя словами, которые повторяются - JavaScript - PullRequest
1 голос
/ 04 апреля 2019

Я пытаюсь узнать количество фруктов и их названия.Сначала я хочу вырезать строку в подстроки, поскольку я знаю, где должно начинаться и заканчиваться предложение.После того, как я получу подстроки, я могу проверить номер и название фрукта.У меня будет массив с названиями фруктов, и будет представлено только одно число для каждой подстроки.

var fruits = ["apple","orange","kiwi","banana"];
var string = 'I want to <start> eat 6 slices of apples <end> in the morning and <start> 1 orange in the evening <end> and <start> 4 more slices of apple before bed <end>'
var pattern = /(?<=<start>\s).*(?=<end>)/g;
var substrings = pattern.exec(string);
var fruit;
for(var i = 0; i < substrings.length; i++){
  for(var j = 0; j < fruits.length; j++){
      fruit = substrings.match(/(fruits[j])/);
   }
  var number = substrings.match(/\d/);
}

Я ожидаю выхода: 10 яблок, 1 апельсин;

Ответы [ 4 ]

1 голос
/ 04 апреля 2019

Я сделал некоторые изменения в вашем коде, и похоже, что он работает:

var fruits = ["apple","orange","kiwi","banana"]
var string = 'I want to <start> eat 6 slices of apples <end> in the morning and <start> 1 orange in the evening <end> and <start> 4 more slices of apple before bed <end>'
var pattern = /\<start\>\s*.*?\<end\>/g
var substrings = string.match(pattern)
var fruitsDict = {};
for(var i = 0; i < substrings.length; i++){
  for(var j = 0; j < fruits.length; j++){
    if (substrings[i].match(RegExp(fruits[j]))) {
      num = substrings[i].match(/\d+/)[0]
      fruitsDict[fruits[j]] = (fruitsDict[fruits[j]] || 0) + parseInt(num)
    }
  }
}
console.log(fruitsDict)
1 голос
/ 04 апреля 2019

Одна идея состоит в том, чтобы захватить (пронумеровать) что-нибудь (somefruit), как регулярное выражение, убедитесь, что он использует глобальный флаг, это позволяет вам зацикливаться для каждого найденного раздела.Использование групп захвата в регулярном выражении упрощает суммирование ...

Таким образом, простое регулярное выражение для этого -> /(\d).*?(apple|orange|kiwi|banana)/g

Также обратите внимание .*?, это называетсянет жадного захвата, если его не использовать, он будет продолжать захват до последнего найденного фрукта.

Ниже я просто затем использую new RegExp для построения вышеприведенного регулярного выражения.

Тогда, потому что я используюГлобальный флаг, который я могу пройти через все найденные термины и суммы.

пс.Для этого не требуются начальные и конечные биты, но вы можете добавить их, если действительно необходимо.

const fruits = ["apple","orange","kiwi","banana"];
const string = 'I want to <start> eat 6 slices of apples <end> in the morning and <start> 1 orange in the evening <end> and <start> 4 more slices of apple before bed <end>'

const find = new RegExp(`(\\d).*?(${fruits.join("|")})`, "g");  //build the regular expression
const sums = {}; //somewhere to store our sums.

while (true) {
  const f = find.exec(string);
  if (!f) break;  //no more found
  const [_, qty, fruit] = f;
  sums[fruit] = (sums[fruit] | 0) + (qty | 0); //sum the results.
}
 
console.log(sums);
0 голосов
/ 04 апреля 2019

Мое предложение:

  • соответствует всем шаблонам
  • для каждого совпадения обновлять объект результата

var fruits = ["apple","orange","kiwi","banana"];
var string = 'I want to <start> eat 60 slices of apples <end> in the morning and <start> 1 orange in the evening <end> and <start> 4 more slices of apple before bed <end>'

var result = {};
string.match(/<start>.[^<>]*<end>/g).forEach(function(ele) {
    var n = +ele.replace(/\D/g,'');
    var x = fruits.find((e) => ele.indexOf(e)>-1);
    result[x] = (result[x] | 0) + n;
});
console.log(result);
0 голосов
/ 04 апреля 2019

У вас мало проблем в коде (исправлено с комментариями):

var fruits = ["apple","orange","kiwi","banana"];
var string = 'I want to <start> eat 6 slices of apples <end> in the morning and <start> 1 orange in the evening <end> and <start> 4 more slices of apple before bed <end>'
// we need .*? to match non greedy otherwise it will match whole string first and last <>
var pattern = /(?<=<start>\s).*?(?=<end>)/g;
while (true) {
  // we need to loop because exec return single match
  var substrings = pattern.exec(string);
  if (!substrings) {
    break;
  }
  var fruit;
  // you don't need a loop because exec will create array with one value
  for(var j = 0; j < fruits.length; j++){
      // to create regex from variable use regex constructor
      var re = new RegExp('(' + fruits[j] + ')');
      fruit = substrings[0].match(re);
      // break the loop or you may have null on next fruit
      if (fruit) {
        break;
      }
   }
   // match any number of digits so it match 10 or 100
   var number = substrings[0].match(/\d+/);
   console.log({number, fruit});
}

var fruits = ["apple","orange","kiwi","banana"];
var fruits_re = new RegExp(fruits.join('|'));

Вы также можете упростить код, создав регулярное выражение для фруктов

var fruits = ["apple","orange","kiwi","banana"];
var fruits_re = new RegExp(fruits.join('|'));
var string = 'I want to <start> eat 6 slices of apples <end> in the morning and <start> 1 orange in the evening <end> and <start> 4 more slices of apple before bed <end>';
var pattern = /(?<=<start>\s).*?(?=<end>)/g;
while (true) {
  var substrings = pattern.exec(string);
  if (!substrings) {
    break;
  }
  var fruit = substrings[0].match(fruits_re);
  var number = substrings[0].match(/\d+/);
  console.log({number, fruit});
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...