Сократить функцию Javascript

Я написал себе функцию, чтобы превратить строку в аббревиатуру, и в настоящее время она довольно длинная и чувствительна к регистру.

Мне нужно укоротить его, чтобы он работал в 100% случаев. В настоящее время он завинчивается, если одно из слов расщепления имеет капитал, если слово заканчивается словом.

Мои разделительные слова - это в основном слова, которые я удаляю (поскольку большинство компаний и их не включают). К ним относятся:

  • и
  • из
  • для
  • до

Кроме того, способ, которым я их удаляю, - использовать split и join (str.split('and ').join('')), который мне кажется не самым простым способом.

Помимо этих проблем, он отлично работает. Может ли кто-нибудь помочь мне сгладить функцию и исправить проблемы? Спасибо.

Функция:  

String.prototype.toAbbrev = function () {
    var s = [];
    var a = this.split('and ').join('').split('of ').join('').split('the').join('').split('for ').join('').split('to ').join('').split(' ');
    for (var i = 1; i < a.length + 1; i++) {
        s.push(a[i - 1].charAt(0).toUpperCase());
    }

    return s.join('.');
}

Выходы на тестируемые компании

The National Aeronautics and Space Administration           ->    N.A.S.A
The National Roads and Motorists' Association               ->    N.R.M.A
Royal Society for the Prevention of Cruelty to Animals      ->    R.S.P.C.A

Ответ 1

Еще более короткий:

str.replace(/(and|of|the|for|to)( |$)/gi, "").replace(/(.).+?(\s|$)/g, "$1.");

Чтобы убедиться, что он заглавный, вы можете сделать .toUpperCase в конце.

(.)     //selects the first character
.+      //matches the rest of the characters
  ?     //? indicates a lazy match
(\s|$)  //match a space or the end

$1.     //means "the first selected match plus a dot"

Пусть превращается в одно Regex!

str.replace(/((and|of|the|for|to) )*(.).+?(\s|$)/ig, "$3.");
"Royal Society for the Prevention of Cruelty to Animals"
    .replace(/((and|of|the|for|to) )*(.).+?(\s|$)/ig, "$3.");
//R.S.P.C.A

"Josie and the Pussycats"
    .replace(/((and|of|the|for|to) )*(.).+?(\s|$)/ig, "$3.");
//J.P.

Это должно теоретически охватывать все законные имена. Для имен с предлогами (именами) в конце вы можете технически сделать это:

.replace(/((and|of|the|for|to) )*(.).+?(\s|$)((and|of|the|for|to) ?)*/ig, "$3.")

Но это явно больше, чем тот, у которого два replace, и это побеждает его цель.

Ответ 2

Я думаю, что такой подход может работать лучше:

var toAbbrev = function(str){
    return str.replace(/\b(?:and|of|the|for|to)(?: |$)/gi,''). // remove all occurances of ignored words
               split(' ').                                     // split into words by spaces
               map(function(x){                          
                   return x.charAt(0).toUpperCase();           // change each word into its first letter capitalized
               }).
               join('.');                                      // join with periods
};

и здесь пробой регулярного выражения:

/
    \b                    // word boundary
    (?:and|of|the|for|to) // non-capturing group. matches and/of/the/for/to
    (?: |$)               // non-capturing group. matches space or end of string
/gi                       // flags: g = global (match all), i = case-insensitive

И здесь альтернативный метод, который имеет менее сложное регулярное выражение:

var toAbbrev = function(str){
    return str.split(' '). // split into words
               filter(function(x){
                   return !/^(?:and|of|the|for|to)$/i.test(x); // filter out excluded words
               }).
               map(function(x){
                    return x.charAt(0).toUpperCase(); // convert to first letter, captialized
               }).
               join('.'); // join with periods
};

И разбивка регулярных выражений:

/
    ^                     // start of string
    (?:and|of|the|for|to) // non-capturing group. matches and/of/the/for/to
    $                     // end of string
/i                        // flags: i = case-insensitive

Ответ 3

Вы также можете сделать это, используя сокращение. То, что вы делаете, по сути сводится к сокращению строки до аббревиатуры -

str.split(' ').reduce(function(preV, curV, index) {
    if(!/^(and|of|the|for|to)$/.test(curV.toLowerCase())) {
        return preV + curV.toUpperCase().charAt(0) + '.';
    }
    return preV;
}, '');

Ответ 4

почему бы не попробовать что-то вроде этого?

var a=this.replace(/and |of |the |for |to /gi, '').split(' ');

В противном случае остальное кажется прекрасным

Ответ 5

Просто замените строку следующим образом:

var a = this.replace(/ and | of | the | for | to /gi, ' ').split(' ');

Это также разрешит проблему одного из слов расщепления, находящихся в конце любого основного слова.

Для удаления любых разделительных слов в начале строки просто выполните следующие действия:

var pos = a.search(/and |of |the |for |to /i);
if (pos == 0)
   //remove that word

Ответ 6

Возможное решение с использованием ECMA5

Javascript

var toAbbrev = (function (ignore) {
    return function toAbbrev(myString) {
        return myString.split(/[^\w]/).reduce(function (acc, word) {
            if (word && ignore.indexOf(word.toLowerCase()) === -1) {
                acc += word.charAt(0).toUpperCase() + '.';
            }

            return acc;
        }, '');
    };
}(['and', 'of', 'the', 'for', 'to']));

console.log(toAbbrev('The Silica & Sand Society'));
console.log(toAbbrev('The National Aeronautics and Space Administration'));
console.log(toAbbrev('The National Roads and Motorists\' Association'));
console.log(toAbbrev('Royal Society for the Prevention of Cruelty to Animals'));

Выход

S.S.S.
N.A.S.A.
N.R.M.A.
R.S.P.C.A. 

Вкл jsFiddle

Возможно, вы могли бы улучшить регулярное выражение split (/[^\w]/) для обработки дополнительных странностей. Или просто разделите пробелы /\s/ и добавьте в список исключений.