1

I need to split a string like this

var val = "$cs+55+mod($a)";

into an array

arr = val.split( /[+-/*()\s*]/ );

The problem is to keep the splitter character as an array element like

arr = [ '$cs', '+', '55', 'mod', '(', '$a', ')' ]

and not like

arr = [ '$cs', '55', 'mod', '$a' ]
Cœur
  • 37,241
  • 25
  • 195
  • 267
DCD
  • 325
  • 6
  • 25
  • do you not want the `+` between `55` and `mod`? or did you mean to write it like this: `arr = [ '$cs', '+', '55','+', 'mod', '(', '$a', ')' ]` ? – Wesley Smith Mar 07 '15 at 16:05
  • I want the '+' between '55' and 'mod'. The problem is that '+' and the other characters of split are not charged as an array element. – DCD Mar 07 '15 at 16:13
  • Have a look on this article, it seems to be what you're looking for: http://stackoverflow.com/questions/12001953/javascript-and-regex-split-string-and-keep-the-separator – Avinor Mar 07 '15 at 16:14
  • Good answers all around! Totally just for fun, here's a performance profile of the top 3 answers (1 of which got deleted) - a roll your own solution, using `.match`, and using regex groups: http://jsperf.com/split-including-split-character – p e p Mar 07 '15 at 16:38
  • @dcd4u2 add the corresponding tag at very first. So that we could also taste the sweet. – Avinash Raj Mar 07 '15 at 17:11

2 Answers2

4

You should use match instead of split.

"$cs+55+mod($a)".match(/([+-/*()\s*]|[^+-/*()\s*]+)/g);

Explanation:

[+-/*()\s*]    -- Your provided regex
[^+-/*()\s*]+  -- Negation of the above regex using ^ and mentioning that could be more than one letter by using +
Mr_Green
  • 40,727
  • 45
  • 159
  • 271
  • 1
    you don't need to use a capturing group, just `"$cs+55+mod($a)".match(/[+-/*()\s*]|[^+-/*()\s*]+/g);` would be fine. – Avinash Raj Mar 07 '15 at 17:08
  • @AvinashRaj strange.. but `match` needs brackets to capture right? How this is working without brackets? – Mr_Green Mar 08 '15 at 05:09
  • who told you that match needs a capturing group? `[+-/*()\s*]` part will do a separate match and `[^+-/*()\s*]+` also will do a separate match. Finally match returns all the matched characters. There is no need to capture anything. – Avinash Raj Mar 08 '15 at 05:10
0

1st thank you all for the help.

My problem is solved but not finished.

Here is a more detailed usage

jsfiddler

$(function() {
var tags = [
    '$c[8][clientes][clientes_iva]',
    '$c[8][paises_iva][paises_iva]',
    '$c[8]',
    'mod(',
    '$user'
];

function split( val ) {
    var arr = val.split( /([+-\/*()\s*]|[^+-\/*()\s*]+)/g );
    return arr;
}

function extractLast( term ) {
    return split( term ).pop();
}

$( "#condition" )
    .bind("keydown", function( event ) {
        if ( event.keyCode === $.ui.keyCode.TAB && $( this ).autocomplete( "instance" ).menu.active ) {
            event.preventDefault();
        }
    })
    .autocomplete({
        minLength: 0,
        source: function( request, response ) {
            response( $.ui.autocomplete.filter( tags, extractLast( request.term ) ) );
        },
        focus: function() {
            return false;
        },
        select: function( event, ui ) {
            var terms = split(this.value);
            terms.pop();
            terms.push( ui.item.value );
            this.value = terms.join( "" );
            return false;
        }
    });

});

I made a Video where you all can see what I'm doing.

DCD
  • 325
  • 6
  • 25