Condense Javascript Function

I created a function for turning strings into abbreviations, but it's currently quite lengthy and case-sensitive.

I'm looking for a way to streamline it so that it functions flawlessly all the time. Right now, it messes up if a splitting word is capitalized or if a word ends with a splitting word.

The words I'm using as splitting words are essentially the ones I want to remove (as most companies don't include them). These words include:

  • and
  • of
  • the
  • for
  • to

Additionally, my current method of removing them involves using split and join (str.split('and ').join('')) which I believe may not be the most efficient approach.

Overall, aside from these issues, the function works well. Can anyone assist me in simplifying the function and addressing the problems? Thank you.

Function:

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('.');
}

Results on Tested Companies

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

Answer №1

Perhaps a more efficient approach could be:

const toAbbreviation = (sentence) => {
    return sentence.split(' ')
                   .map((word) => word.charAt(0).toUpperCase())
                   .join('.');
};

Here's how the regular expression works in this case:

/
    \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

An alternative method with a simpler regular expression is also available:

const toAbbreviation = (str) => {
    return str.split(' ')
              .filter((word) => ! /^(?:and|of|the|for|to)$/i.test(word))
              .map((word) => word.charAt(0).toUpperCase())
              .join('.');
};

Regular expression breakdown:

/
    ^                     // 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

Answer №2

Here's an even more concise solution:

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

If you want to ensure capitalization, simply add .toUpperCase at the end.

(.)     //selects the first character
.+      //matches the remaining characters
 ?      //lazy match indicator
(\s|$)  //match for a space or end of string

$1.     //replaces with "first selected match plus dot"

Let's combine these into one 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.

This regex should cover all legitimate names. For names ending with prepositions, you could technically use:

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

However, this is longer than the dual replace method and goes against its purpose.

Answer №3

Another approach would be to utilize the reduce method for achieving the desired outcome of abbreviating a string -

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

Answer №4

Have you considered using a different approach like the following?

let b = str.replace(/and |of |the |for |to /gi, '').split(' ');

Everything else looks good as it is.

Answer №5

To solve this problem, simply use a string replacement method like the one shown below:

let str = myString.replace(/ and | of | the | for | to /gi, ' ').split(' ');

This approach will also fix any issues with splitting words that are attached to the end of main words.

If you need to get rid of any splitting words at the beginning of the string, follow these steps:

let position = str.search(/and |of |the |for |to /i);
if (position == 0) {
   // Remove that word
}

Answer №6

A potential solution utilizing ECMA5 standard

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'));

Result

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

Located on jsFiddle

You might want to enhance the split regex (/[^\w]/) to accommodate more unusual cases. Alternatively, you can split based on whitespace /\s/ and add it to the exclusion list.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

PhantomJS encountered an issue: Attempting to access the 'write' member of a deleted QObject is not allowed

I am in the process of creating a web API on port 7788 that will accept JSON data. This JSON data will then be passed to my API which will render a website. Next, PhantomJS will search for an element on that page and the web API on port 7788 should return ...

Manipulating elements in jQuery arrays: addition and removal

When working with an input field that has a value of "hello1,hello2" as shown below: <input type="text" value="hello1,hello2" id="list"> To convert this value into an array using the .split() method, you can do the following: var list = $('#l ...

Giving identification to a pair of elements located within the same column

Struggling with assigning IDs to two elements in a single column - a dropdown and a text element. Managed it in the first scenario, but encountering issues in the second one. Seeking assistance on this matter. Scenario 1: <td> <sele ...

Error encountered while attempting to compile transcluded directives during unit testing with Angular version 1.3.0

I am facing an issue with a custom directive having transclude: true property. The directive contains a template pointing to a simple HTML file with an anchor element having an ng-transclude attribute. The anchor element wraps the content of the directive. ...

Having issues with Twitter typeahead bloodhound tokens not functioning properly

Why are the tokens not working? I expect 'Inkoopverenigingen' to be suggested when typing 'east', 'home', or 'trap'. json: [ { "value": "Inkoopverenigingen", "tokens": [ "inkoopverenigingen", ...

Add the content of a JavaScript variable to a label without using any scripting

Is there a way to concatenate the value of a JavaScript variable with a label without utilizing jQuery? For example: Var global_message = "1234"; <label id="my-label">Test</label> I desire the concatenated value "Test1234" to be displayed o ...

Generate a new perspective by incorporating two distinct arrays

I have two arrays containing class information. The first array includes classId and className: classes = [ {classid : 1 , classname:"class1"},{classid : 2 , classname:"class2"},{classid : 3 , classname:"class3"}] The secon ...

Ways to enhance the capabilities of blueprints within Sails.js without completely replacing the entire blueprint functionality

I have been struggling with a challenge for some time now, trying to implement a feature that is commonly seen in web applications. As someone who is new to sails.js and web development in general, I am open to any corrections on my use of terminology or m ...

Creating a flexible array in VUE.JS

(I would like to mention that I am utilizing the v-calendar plugin) I recently started working with vue.js and have been facing a challenge for some time now. I am trying to track button clicks and pass this information down to a component by toggling the ...

Modify the value of a variable inside another {{variable}} (not sure what it's called)

I am looking to update the variable "prefs" to reflect either "easy, medium, or hard" options based on user interaction. For instance: THIS {{choice.prefs.title}} NEEDS TO BE UPDATED TO {{choice.easy.price}} or {{choice.medium.price}} or {{choice.hard. ...

Triggering a keyboard *ENTER* event on an Input in Javascript/React by clicking a button is a common query among developers

I am facing a challenge with an Input element that only displays results when I press Enter on the keyboard. The element is part of a third-party extension, so my control over it is limited. My goal is to trigger the ENTER event for the Input when a button ...

The error message encountered in React says, "Trying to access the 'toString' property of an undefined object leads to a TypeError

Currently, I'm working on a project using the MERN stack. In this project, there's an endPoint for users to update their details. router.put('/updateuser/:id',fetchuser, async (req, res) => { const {name, email, role, password} ...

Acquire image dimensions with Javascript when uploading a file

I am working with a file upload interface where users will be uploading images. My goal is to validate the height and width of the image on the client side. Is there a way to determine the size of an image using just the file path in JavaScript? Important ...

tips for extracting data from a json array

Hello everyone, I have a question that I could use some help with. I have a set of data that looks like this: var data = { "values":[[1,2,3],[2,4,3],[3,6,7],[1,4],[6,4,3,4],[6,7,3,5]] } Currently, I am trying to create a multiple line chart usi ...

Exploring sections on a Three.js Cylinder

Playing around with Cylinder Geometry from Three.js is so much fun! You can check out the documentation here. Here's my CodePen where I've been experimenting: https://codepen.io/lklancir/pen/pdaPoY var gui = new dat.GUI(); var s ...

`I'm experiencing issues with my AJAX call when using Django`

As part of my blog practice, I'm trying to ensure that all notifications are marked as seen when a user views them. This functionality works fine when I manually go to the URL, but it's not working when using Ajax. Here is the JavaScript code: ...

Parsing JSON with the nodejs JSON.parse() method from the Stack Overflow API

Check out the code snippet below: const request = require('request'); const API = "https://api.stackexchange.com/2.2/users?page=1&order=desc&sort=reputation&site=stackoverflow"; request(API, function(e//console.dir(body); if( err || ...

Struggling with Angular 8: Attempting to utilize form data for string formatting in a service, but encountering persistent page reloading and failure to reassign variables from form values

My goal is to extract the zip code from a form, create a URL based on that zip code, make an API call using that URL, and then display the JSON data on the screen. I have successfully generated the URL and retrieved the necessary data. However, I am strug ...

How can the printing of content be adjusted when the browser zoom function is activated?

Is there a way to prevent the content from zooming when printing while the browser is zoomed in? The goal is for the printing (using iframe) to remain unchanged even if the browser is zoomed. I attempted: document.body.style.transformOrigin = 'top le ...

Error: The sort method cannot be applied to oResults as it is not a

I encountered this issue. $.ajax({ url: '${searchPatientFileURL}', data: data, success: function(oResults) { console.log("Results:...->"+oResults); oResults.sort(function ...