Вставка пробела после каждого экземпляра строки в строке - PullRequest
1 голос
/ 07 ноября 2019

Я пытаюсь разделить слова в строке пробелами.

Например, я хотел бы преобразовать "twothousandninehundredfiftyeight" в "two thousand nine hundred fifty eight" (так что позже я могу преобразовать его в 2958, но яя уже понял это)

Мне удалось заставить его работать, используя словарь массива:

var dictionary = ["one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty","thirty","fourty","forty","fifty","sixty","seventy","eighty","ninety","hundred","thousand"];

Наряду с этими двумя функциями:

function spaceinsert(x) {
  for (i = 0; i < dictionary.length; i++) {
    if (x.includes(dictionary[i])) {
      var pos = getIndicesOf(dictionary[i], x);
      for (g = 0; g < pos.length; g++) {
            if (pos[g] != -1 && pos[g] !=0) {
                x = [x.slice(0, pos[g]), " ", x.slice(pos[g])].join('');    
            }
      }
    }
  }
  return x
}

и

function getIndicesOf(searchStr, str, caseSensitive) {
    var searchStrLen = searchStr.length;
    if (searchStrLen == 0) {
        return [];
    }
    var startIndex = 0, index, indices = [];
    if (!caseSensitive) {
        str = str.toLowerCase();
        searchStr = searchStr.toLowerCase();
    }
    while ((index = str.indexOf(searchStr, startIndex)) > -1) {
        indices.push(index);
        startIndex = index + searchStrLen;
    }
    return indices;
}

(извините за грязный код, я новичок в этом)

Это прекрасно работает для большинства номеров. Например:

onethousandthreehundredsixtyfive преобразуется в one thousand three hundred sixty five, но не работает с другими числами, такими как seventhousandtwohundredtwentytwo, преобразуется в seven thousand two hundredtwent ytwo. sixthousandfourhundredeightyeight преобразуется в six thousand four hundred eight yeight Я думаю, что это связано с повторяющимся словом "( TWO сто двадцать) TWO ), но я не могу найти решение этой проблемы.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 08 ноября 2019

Вы можете выполнять обе работы за один раз. Не нужно разделять слова пробелом, а затем конвертировать новую строку в число. Просто зацикливайте строку по одному слову за раз и конвертируйте по мере необходимости.

Для этого вам понадобится массив dictionary объектов, например:

var dictionary = [ { name: "one", value: 1 }, { name: "two", value: 2 }, ... ];

Где вы 'Сначала нужно поставить составные числа, что означает fourteen, sixteen, seventeen, eighteen, nineteen, fourty (что, кстати, неправильно), sixty, seventy, eighty и ninety должны идти первыми, чтобы они имели более высокий приоритет, поэтому sixty будет сопоставляться как sixty, а не как six, что сохранит ty, что приведет к ошибкам. Конечный массив dictionary:

const dictionary = [ { name: "fourteen", value: 14 }, { name: "sixteen", value: 16 }, { name: "seventeen", value: 17 }, { name: "eighteen", value: 18 }, { name: "nineteen", value: 19 }, { name: "fourty", value: 40 }, { name: "sixty", value: 60 }, { name: "seventy", value: 70 }, { name: "eighty", value: 80 }, { name: "ninety", value: 90 }, { name: "one", value: 1 }, { name: "two", value: 2 }, { name: "three", value: 3 }, { name: "four", value: 4 }, { name: "five", value: 5 }, { name: "six", value: 6 }, { name: "seven", value: 7 }, { name: "eight", value: 8 }, { name: "nine", value: 9 }, { name: "ten", value: 10 }, { name: "eleven", value: 11 }, { name: "twelve", value: 12 }, { name: "thirteen", value: 13 }, { name: "fifteen", value: 15 }, { name: "twenty", value: 20 }, { name: "thirty", value: 30 }, { name: "forty", value: 40 }, { name: "fifty", value: 50 }, { name: "hundred", value: 100 }, { name: "thousand", value: 1000 } ];

И код, который выполняет обе работы за один раз:

function convert(str) {
   let number = 0, current = 0;                                                   // the resulting number and the current accumulated number (both initialized to 0)

   while(str.length) {                                                            // while there is still text in our string
      let item = dictionary.find(item => str.indexOf(item.name) === 0);           // find the item from dictionary at the begining of the string str (here the order of items in dictionary is important, meaning it tries to match "sixty" before it tries "six")

      if(item == null) {                                                          // if no item is found
         throw "syntax error: item could not be matched at: '" + str + "'";       // throw an error
      }

      if(item.value === 100 || item.value === 1000) {                             // if the item is 100 or 1000
         current *= item.value;                                                   // multipy it by the current amount being accumulated
      } else {                                                                    // otherwise
         number += current;                                                       // add the amount accumulated to number
         current = item.value;                                                    // and start accumulating a new amount
      }

      str = str.slice(item.name.length);                                          // move to the next item by cutting the current item out
   }

   return number + current;                                                       // don't forget the last accumulated amount
}

Пример:

const dictionary = [ { name: "fourteen", value: 14 }, { name: "sixteen", value: 16 }, { name: "seventeen", value: 17 }, { name: "eighteen", value: 18 }, { name: "nineteen", value: 19 }, { name: "fourty", value: 40 }, { name: "sixty", value: 60 }, { name: "seventy", value: 70 }, { name: "eighty", value: 80 }, { name: "ninety", value: 90 }, { name: "one", value: 1 }, { name: "two", value: 2 }, { name: "three", value: 3 }, { name: "four", value: 4 }, { name: "five", value: 5 }, { name: "six", value: 6 }, { name: "seven", value: 7 }, { name: "eight", value: 8 }, { name: "nine", value: 9 }, { name: "ten", value: 10 }, { name: "eleven", value: 11 }, { name: "twelve", value: 12 }, { name: "thirteen", value: 13 }, { name: "fifteen", value: 15 }, { name: "twenty", value: 20 }, { name: "thirty", value: 30 }, { name: "forty", value: 40 }, { name: "fifty", value: 50 }, { name: "hundred", value: 100 }, { name: "thousand", value: 1000 } ];

function convert(str) {
   let number = 0, current = 0;

   while(str.length) {
      let item = dictionary.find(item => str.indexOf(item.name) === 0);
  
      if(item == null) {
         throw "syntax error: item could not be matched at: '" + str + "'";
      }

      if(item.value === 100 || item.value === 1000) {
         current *= item.value;
      } else {
         number += current;
         current = item.value;
      }

      str = str.slice(item.name.length);
   }

   return number + current;
}

console.log(convert("twothousandninehundredfiftyeight"));
console.log(convert("seventhousandtwohundredtwentytwo"));
console.log(convert("onethousandthreehundredsixtyfive"));
1 голос
/ 07 ноября 2019

Сортируйте словарь по длине, чтобы сначала обрабатывались самые длинные слова, чтобы, например, не разделить «четырнадцать» на «четыре подростка».

Создать RegExp, соединив слова словаря на | и перенос в группу с круглыми скобками. Используйте флаги gi (глобальные, без учета регистра). См. regex101 для получения дополнительной информации о RegExp.

Теперь используйте String.replace() с шаблоном и заменяйте каждое совпадение соответствием + пробел. Обрезать результат, чтобы удалить пробел после строки.

const str = "twothousandninehundredfiftyeight"

var dictionary = ["one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty","thirty","fourty","forty","fifty","sixty","seventy","eighty","ninety","hundred","thousand"].sort((a, b) => b.length - a.length)

const pattern = new RegExp(dictionary.join('|'), 'gi')

const result = str.replace(pattern, '$& ').trim()

console.log(result)
...