简体   繁体   中英

Remove all dots except the first one from a string

Given a string

'1.2.3.4.5'

I would like to get this output

'1.2345'

(In case there are no dots in the string, the string should be returned unchanged.)

I wrote this

function process( input ) {
    var index = input.indexOf( '.' );

    if ( index > -1 ) {
        input = input.substr( 0, index + 1 ) + 
                input.slice( index ).replace( /\./g, '' );
    }

    return input;
}

Live demo: http://jsfiddle.net/EDTNK/1/

It works but I was hoping for a slightly more elegant solution...

There is a pretty short solution (assuming input is your string):

var output = input.split('.');
output = output.shift() + '.' + output.join('');

If input is " 1.2.3.4 ", then output will be equal to " 1.234 ".

See this jsfiddle for a proof. Of course you can enclose it in a function, if you find it necessary.

EDIT:

Taking into account your additional requirement (to not modify the output if there is no dot found), the solution could look like this:

var output = input.split('.');
output = output.shift() + (output.length ? '.' + output.join('') : '');

which will leave eg. " 1234 " (no dot found) unchanged. See this jsfiddle for updated code.

It would be a lot easier with reg exp if browsers supported look behinds.

One way with a regular expression:

function process( str ) {
    return str.replace( /^([^.]*\.)(.*)$/, function ( a, b, c ) { 
        return b + c.replace( /\./g, '' );
    });
}

You can try something like this:

str = str.replace(/\./,"#").replace(/\./g,"").replace(/#/,".");

But you have to be sure that the character # is not used in the string; or replace it accordingly.

Or this, without the above limitation:

str = str.replace(/^(.*?\.)(.*)$/, function($0, $1, $2) {
  return $1 + $2.replace(/\./g,"");
});

You could also do something like this, i also don't know if this is "simpler", but it uses just indexOf, replace and substr.

var str = "7.8.9.2.3";
var strBak = str;

var firstDot = str.indexOf(".");
str = str.replace(/\./g,"");
str = str.substr(0,firstDot)+"."+str.substr(1,str.length-1);

document.write(str);

Shai.

This isn't necessarily more elegant, but it's another way to skin the cat:

var process = function (input) {
    var output = input;

    if (typeof input === 'string' && input !== '') {
        input = input.split('.');
        if (input.length > 1) {
            output = [input.shift(), input.join('')].join('.');
        }
    }

    return output;
};

Here is another approach:

function process(input) {
    var n = 0;
    return input.replace(/\./g, function() { return n++ > 0 ? '' : '.'; });
}

But one could say that this is based on side effects and therefore not really elegant.

Trying to keep this as short and readable as possible, you can do the following:

JavaScript

var match = string.match(/^[^.]*\.|[^.]+/g);
string = match ? match.join('') : string;

Requires a second line of code, because if match() returns null , we'll get an exception trying to call join() on null . (Improvements welcome.)

Objective-J / Cappuccino (superset of JavaScript)

string = [string.match(/^[^.]*\.|[^.]+/g) componentsJoinedByString:''] || string;

Can do it in a single line, because its selectors (such as componentsJoinedByString: ) simply return null when sent to a null value, rather than throwing an exception.

As for the regular expression, I'm matching all substrings consisting of either (a) the start of the string + any potential number of non-dot characters + a dot , or (b) any existing number of non-dot characters . When we join all matches back together, we have essentially removed any dot except the first.

var input = '14.1.2';
reversed = input.split("").reverse().join("");
reversed = reversed.replace(\.(?=.*\.), '' );
input = reversed.split("").reverse().join("");

Based on @Tadek's answer above. This function takes other locales into consideration.


For example, some locales will use a comma for the decimal separator and a period for the thousand separator (eg -451.161,432e-12 ).

First we convert anything other than 1) numbers; 2) negative sign; 3) exponent sign into a period ( "-451.161.432e-12" ).

Next we split by period ( ["-451", "161", "432e-12"] ) and pop out the right-most value ( "432e-12" ), then join with the rest ( "-451161.432e-12" )

(Note that I'm tossing out the thousand separators, but those could easily be added in the join step ( .join(',') )

var ensureDecimalSeparatorIsPeriod = function (value) {
    var numericString = value.toString();
    var splitByDecimal = numericString.replace(/[^\d.e-]/g, '.').split('.');
    if (splitByDecimal.length < 2) {
        return numericString;
    }
    var rightOfDecimalPlace = splitByDecimal.pop();
    return splitByDecimal.join('') + '.' + rightOfDecimalPlace;
};

 let str = "12.1223....1322311.."; let finStr = str.replace(/(\\d*.)(.*)/, '$1') + str.replace(/(\\d*.)(.*)/, '$2').replace(/\\./g,''); console.log(finStr) 

const [integer, ...decimals] = '233.423.3.32.23.244.14...23'.split('.');
const result = [integer, decimals.join('')].join('.')

Same solution offered but using the spread operator. It's a matter of opinion but I think it improves readability.

Not sure what is supposed to happen if "." is the first character, I'd check for -1 in indexOf, also if you use substr once might as well use it twice.

if ( index != -1 ) {
    input = input.substr( 0, index + 1 ) + input.substr(index + 1).replace( /\./g, '' );
}
var i = s.indexOf(".");
var result = s.substr(0, i+1) + s.substr(i+1).replace(/\./g, "");

Somewhat tricky. Works using the fact that indexOf returns -1 if the item is not found.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM