Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #25093 > unrolled thread

Cannot manipulate array produced with string.match

Started bySteveYoungTbird <stephen.young@chello.at>
First post2014-06-27 09:17 +0200
Last post2014-06-27 19:31 +0700
Articles 12 — 4 participants

Back to article view | Back to comp.lang.javascript


Contents

  Cannot manipulate array produced with string.match SteveYoungTbird <stephen.young@chello.at> - 2014-06-27 09:17 +0200
    Re: Cannot manipulate array produced with string.match Denis McMahon <denismfmcmahon@gmail.com> - 2014-06-27 10:02 +0000
      Re: Cannot manipulate array produced with string.match SteveYoungTbird <stephen.young@chello.at> - 2014-06-27 20:00 +0200
        Re: Cannot manipulate array produced with string.match Denis McMahon <denismfmcmahon@gmail.com> - 2014-06-27 19:13 +0000
          Re: Cannot manipulate array produced with string.match SteveYoungTbird <stephen.young@chello.at> - 2014-06-27 22:18 +0200
            Re: Cannot manipulate array produced with string.match SteveYoungTbird <stephen.young@chello.at> - 2014-06-27 23:24 +0200
              Re: Cannot manipulate array produced with string.match Denis McMahon <denismfmcmahon@gmail.com> - 2014-06-28 01:07 +0000
                Re: Cannot manipulate array produced with string.match Denis McMahon <denismfmcmahon@gmail.com> - 2014-06-28 01:16 +0000
              Re: Cannot manipulate array produced with string.match Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-06-28 23:53 +0200
                Re: Cannot manipulate array produced with string.match SteveYoungTbird <stephen.young@chello.at> - 2014-06-29 22:24 +0200
                  Re: Cannot manipulate array produced with string.match Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2014-06-29 23:19 +0200
    Re: Cannot manipulate array produced with string.match JJ <jj4public@vfemail.net> - 2014-06-27 19:31 +0700

#25093 — Cannot manipulate array produced with string.match

FromSteveYoungTbird <stephen.young@chello.at>
Date2014-06-27 09:17 +0200
SubjectCannot manipulate array produced with string.match
Message-ID<loj5qn$cof$1@dont-email.me>
I have produced an array using:

var arr = [];
arr = string.match(/(?:^| )([a-zäöüß]+)(?= [A-Z])/g);

This works as expected and the array is full and can be seen using
console.log or alert().

The array consists of words which I need to filter, so I am trying to
use .splice to remove unwanted instances of the same word using:

for (var i = arr.length - 1; i >= 0; i--) {
    if (arr[i] === 'jim') {
        arr.splice(i, 1);
    }
}

The for loop doesn't recognize any instances of, for instance, 'jim' in
the array although there are several.

I tried the loop using an array I made myself and it worked fine, ie:

arr = ['jim', 'bob', 'arthur', 'jim', 'fred']

What is it about the array produced by the string.match that I am not
understanding? Any help would be much appreciated.

[toc] | [next] | [standalone]


#25097

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2014-06-27 10:02 +0000
Message-ID<lojfg6$i56$2@dont-email.me>
In reply to#25093
On Fri, 27 Jun 2014 09:17:43 +0200, SteveYoungTbird wrote:

> I have produced an array using:
> 
> var arr = [];
> arr = string.match(/(?:^| )([a-zäöüß]+)(?= [A-Z])/g);
> 
> This works as expected and the array is full and can be seen using
> console.log or alert().
> 
> The array consists of words which I need to filter, so I am trying to
> use .splice to remove unwanted instances of the same word using:
> 
> for (var i = arr.length - 1; i >= 0; i--) {
>     if (arr[i] === 'jim') {
>         arr.splice(i, 1);
>     }
> }
> 
> The for loop doesn't recognize any instances of, for instance, 'jim' in
> the array although there are several.
> 
> I tried the loop using an array I made myself and it worked fine, ie:
> 
> arr = ['jim', 'bob', 'arthur', 'jim', 'fred']
> 
> What is it about the array produced by the string.match that I am not
> understanding? Any help would be much appreciated.

Try using the following:

var i = arr.length;
while ( i-- )
    if (arr[i] === 'jim')
        arr.splice(i, 1);
    else
        console.log( "'" + arr[i].toString() + "' !== 'jim'" );

See what console.log is showing for words that don't match jim which you 
expected to match jim.

-- 
Denis McMahon, denismfmcmahon@gmail.com

[toc] | [prev] | [next] | [standalone]


#25103

FromSteveYoungTbird <stephen.young@chello.at>
Date2014-06-27 20:00 +0200
Message-ID<lokbfi$vac$1@dont-email.me>
In reply to#25097
On 06/27/2014 12:02 PM, Denis McMahon wrote:
> On Fri, 27 Jun 2014 09:17:43 +0200, SteveYoungTbird wrote:
> 
>> I have produced an array using:
>>
>> var arr = [];
>> arr = string.match(/(?:^| )([a-zäöüß]+)(?= [A-Z])/g);
>>
>> This works as expected and the array is full and can be seen using
>> console.log or alert().
>>
>> The array consists of words which I need to filter, so I am trying to
>> use .splice to remove unwanted instances of the same word using:
>>
>> for (var i = arr.length - 1; i >= 0; i--) {
>>     if (arr[i] === 'jim') {
>>         arr.splice(i, 1);
>>     }
>> }
>>
>> The for loop doesn't recognize any instances of, for instance, 'jim' in
>> the array although there are several.
>>
>> I tried the loop using an array I made myself and it worked fine, ie:
>>
>> arr = ['jim', 'bob', 'arthur', 'jim', 'fred']
>>
>> What is it about the array produced by the string.match that I am not
>> understanding? Any help would be much appreciated.
> 
> Try using the following:
> 
> var i = arr.length;
> while ( i-- )
>     if (arr[i] === 'jim')
>         arr.splice(i, 1);
>     else
>         console.log( "'" + arr[i].toString() + "' !== 'jim'" );
> 
> See what console.log is showing for words that don't match jim which you 
> expected to match jim.
> 

I did as you  suggested and strangely the alert reads " 'jim' !== 'jim'
" as well as all of the other names not being equal to 'jim'

However if I use the array :-

arr = ['jim', 'bob', 'arthur', 'jim', 'fred']

the jim's are removed.

[toc] | [prev] | [next] | [standalone]


#25104

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2014-06-27 19:13 +0000
Message-ID<lokfoe$q6k$1@dont-email.me>
In reply to#25103
On Fri, 27 Jun 2014 20:00:18 +0200, SteveYoungTbird wrote:

> I did as you  suggested and strangely the alert reads " 'jim' !== 'jim'
> " as well as all of the other names not being equal to 'jim'

Hmm, now you need to figure out what the differences are.

I noticed that your original post had characters outside of the basic 7 
bit ascii character set. Is it possible that you are comparing characters 
in different encodings?

For example if 'jim' contains any of these characters, and 'jim' in your 
program code is in utf-8, but 'jim' in your string is in some other 
character set, then the representations of the non ascii characters might 
be different even though they look the same.

-- 
Denis McMahon, denismfmcmahon@gmail.com

[toc] | [prev] | [next] | [standalone]


#25105

FromSteveYoungTbird <stephen.young@chello.at>
Date2014-06-27 22:18 +0200
Message-ID<lokjjc$o0v$1@dont-email.me>
In reply to#25104
On 06/27/2014 09:13 PM, Denis McMahon wrote:
> On Fri, 27 Jun 2014 20:00:18 +0200, SteveYoungTbird wrote:
> 
>> I did as you  suggested and strangely the alert reads " 'jim' !== 'jim'
>> " as well as all of the other names not being equal to 'jim'
> 
> Hmm, now you need to figure out what the differences are.
> 
> I noticed that your original post had characters outside of the basic 7 
> bit ascii character set. Is it possible that you are comparing characters 
> in different encodings?
> 
> For example if 'jim' contains any of these characters, and 'jim' in your 
> program code is in utf-8, but 'jim' in your string is in some other 
> character set, then the representations of the non ascii characters might 
> be different even though they look the same.
> 

Ah, that sounds like a likely reason. The text that I am using .match on
is read from a German RSS feed.

Is there any way of converting it to utf-8 in javaScript if it is not
already so encoded?

[toc] | [prev] | [next] | [standalone]


#25106

FromSteveYoungTbird <stephen.young@chello.at>
Date2014-06-27 23:24 +0200
Message-ID<loknef$inh$1@dont-email.me>
In reply to#25105
On 06/27/2014 10:18 PM, SteveYoungTbird wrote:
> On 06/27/2014 09:13 PM, Denis McMahon wrote:
>> On Fri, 27 Jun 2014 20:00:18 +0200, SteveYoungTbird wrote:
>>
>>> I did as you  suggested and strangely the alert reads " 'jim' !== 'jim'
>>> " as well as all of the other names not being equal to 'jim'
>>
>> Hmm, now you need to figure out what the differences are.
>>

Got it! arr.match produces a string with a space after the comma.
Therefore 'jim' in the loop was actually ' jim' and therefore didn't match,

Thanks for your help.

[toc] | [prev] | [next] | [standalone]


#25107

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2014-06-28 01:07 +0000
Message-ID<lol4g3$or3$1@dont-email.me>
In reply to#25106
On Fri, 27 Jun 2014 23:24:31 +0200, SteveYoungTbird wrote:

> Got it! arr.match produces a string with a space after the comma.
> Therefore 'jim' in the loop was actually ' jim' and therefore didn't
> match,

Observation: You had all the information you needed to solve this, you 
just needed to figure out how to view that information. :)

If you wanted a really deep dissection of the compares to the console you 
could use something like the following, which prints length, character 
and character code mismatches:

var arr = ["fred","jim","pete"," jim","andrew"," jim ","bert",
           "jim ","henry","jim","mike"];
var i = arr.length, j, k;

console.log( arr.toString() );

while ( i-- ) {
    if (arr[i] === 'jim') {
        arr.splice(i, 1);
    }
    else {
        console.log( "'" + arr[i].toString() + "' !== 'jim'" );
        if ( arr[i].toString().length != "jim".length ) {
            console.log( "'" + arr[i].toString() + "'.length = " + 
                         arr[i].toString().length + 
                         " != 'jim'.length = " + "jim".length );
        }
        k = arr[i].toString().length > "jim".length ? 
            arr[i].toString().length : 
            "jim".length;
        for ( j = 0; j < k; j++ ) {
            if ( arr[i].toString().charAt(j) !== "jim".charAt(j) ) {
                console.log( "arr[i].toString().charAt(j) [" + 
                             arr[i].toString().charAt(j) + 
                             "] !== 'jim'.charAt(j) [" + 
                             "jim".charAt(j) + "]" );
            }
            if ( arr[i].toString().charCodeAt(j) !== 
                 "jim".charCodeAt(j) ) {
                console.log( "arr[i].toString().charCodeAt(j) [" + 
                             arr[i].toString().charCodeAt(j) + 
                             "] !== 'jim'.charCodeAt(j) [" + 
                             "jim".charCodeAt(j) + "]" );
            }
        }
    }
}

console.log( arr.toString() );

-- 
Denis McMahon, denismfmcmahon@gmail.com

[toc] | [prev] | [next] | [standalone]


#25108

FromDenis McMahon <denismfmcmahon@gmail.com>
Date2014-06-28 01:16 +0000
Message-ID<lol51s$or3$2@dont-email.me>
In reply to#25107
On Sat, 28 Jun 2014 01:07:15 +0000, Denis McMahon wrote:

> [code]

Better solution:

var arr = ["fred","jim","pete"," jim","andrew"," jim ","bert",
           "jim ","henry","jim","mike"];
var i = arr.length, j, k;

console.log( arr.toString() );

while ( i-- ) {
    if (arr[i] === 'jim') {
        arr.splice(i, 1);
    }
    else {
        console.log( "'" + arr[i].toString() + "' !== 'jim'" );
        if ( arr[i].toString().length != "jim".length ) {
            console.log( "'" + arr[i].toString() + "'.length [" +
                         arr[i].toString().length +
                         "] != 'jim'.length [" + "jim".length + "]" );
        }
        k = arr[i].toString().length > "jim".length ?
            arr[i].toString().length :
            "jim".length;
        for ( j = 0; j < k; j++ ) {
            if ( arr[i].toString().charAt(j) !== "jim".charAt(j) ) {
                console.log( "arr[i].toString().charAt(" + j + ") [" +
                             arr[i].toString().charAt(j) +
                             "] !== 'jim'.charAt(" + j + ") [" +
                             "jim".charAt(j) + "]" );
            }
            if ( arr[i].toString().charCodeAt(j) !==
                 "jim".charCodeAt(j) ) {
                console.log( "arr[i].toString().charCodeAt(" + j +
                             ") [" + arr[i].toString().charCodeAt(j) +
                             "] !== 'jim'.charCodeAt(" + j + ") [" +
                             "jim".charCodeAt(j) + "]" );
            }
        }
    }
}

console.log( arr.toString() );

-- 
Denis McMahon, denismfmcmahon@gmail.com

[toc] | [prev] | [next] | [standalone]


#25110

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2014-06-28 23:53 +0200
Message-ID<1892446.4VnW0yGc5p@PointedEars.de>
In reply to#25106
SteveYoungTbird wrote:

> On 06/27/2014 10:18 PM, SteveYoungTbird wrote:
>> On 06/27/2014 09:13 PM, Denis McMahon wrote:
>>> On Fri, 27 Jun 2014 20:00:18 +0200, SteveYoungTbird wrote:
>>>> I did as you  suggested and strangely the alert reads " 'jim' !== 'jim'
>>>> " as well as all of the other names not being equal to 'jim'
>>> Hmm, now you need to figure out what the differences are.
> 
> Got it! arr.match produces a string with a space after the comma.

s/arr/string/

> Therefore 'jim' in the loop was actually ' jim' and therefore didn't
> match,

It produces that because you have /(?:^| )/ in

>>>>>> var arr = [];
              ^^^^^[1][2]
>>>>>> arr = string.match(/(?:^| )([a-zäöüß]+)(?= [A-Z])/g);
                        [3]^^^^^^^^[4]-------^^^^^^^^^^^[5]

The /(?:…)/ only prevents capturing; it is _not_ a zero-length lookbehind 
(/(?<!…)/ would be, but it is not supported in ECMAScript as yet).

Many parts of this code do not make sense:

 [1] These languages use dynamic type-checking.  You do not need to
     initialize a variable that you will assign a reference to an Array
     instance with a reference to an Array instance.

 [2] No additional initialization is necessary.  String.prototype.match()
     always returns a reference to an Array instance if successful
     (otherwise “null” which overwrites the previous value anyway).

 [3] /(?:^| )…/g does not make sense, see above.

 [4] Capturing the sequence of word characters does not make sense with
     the global flag, as the resulting Array only contains the matches
     as primitive string values, if any.

 [5] /…(?= [A-Z])/g (zero-length positive lookahead) does not appear to
     make sense when you want to match/filter words.  Why would you only
     match words that precede a word starting with a capital letter?
     What about multiple spaces, tabs, and newlines?

In order to match words, simply match consecutive word characters (for the 
non-word characters delimit words and are not matched):

  var arr = string.match(/[a-zäöüß]+/ig);  

JSX:regexp.js can help there with basic support for Unicode character 
properties, like \p{L} for all letters.  But if you want to use .match() 
instead of .exec() then, you need to cast the String to a jsx.regexp.String:

  /* 
   * ["Über", "sprießende", "Äcker", "liefen", "zwölf", "Hühner",  
   *  "sagte", "der", "Bär", "in", "der", "Öffentlichkeit"]
   */
  new jsx.regexp.String(
    "Über sprießende Äcker liefen zwölf Hühner, sagte der Bär"
    + " in der Öffentlichkeit."
  ).match(new jsx.regexp.RegExp("\\p{L}+", "g"))

(You could say that this sentence – that just came to my mind – is an umlaut 
pangram, as a proof-of-concept.  It also features the sz ligature, used as 
in non-reformed Federal German spelling.)

See also:

  - <http://PointedEars.de/scripts/test/regexp>
  - <http://stackoverflow.com/a/8568325/855543>
  - My sig for the source code.

In order to filter out words, simply match on them or replace them.  There 
is no need for array iteration.

That said, Array.prototype.filter() (ES 5+) and equivalents are more 
efficient here than multiple Array.prototype.splice(), even though you 
cleverly iterate in reverse order so that the changed length does not 
matter.

Please post using your real name.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#25123

FromSteveYoungTbird <stephen.young@chello.at>
Date2014-06-29 22:24 +0200
Message-ID<lopsmb$uvo$1@dont-email.me>
In reply to#25110
On 06/28/2014 11:53 PM, Thomas 'PointedEars' Lahn wrote:

> 
>  [5] /…(?= [A-Z])/g (zero-length positive lookahead) does not appear to
>      make sense when you want to match/filter words.  Why would you only
>      match words that precede a word starting with a capital letter?
>      What about multiple spaces, tabs, and newlines?

I am trying to identify German adjectives in a text. I thought that if I
made an array of all the words that appeared before a noun (always
capitalized in German) and then removed definite and indefinite
articles, personal pronouns and other common words such as "von" etc I
could then check the remaining words against an array of German
adjectives. I would be grateful if someone could show me a better way.

> 
> In order to filter out words, simply match on them or replace them.  There 
> is no need for array iteration.

I have explained why I think there is a need for array iteration above

> Please post using your real name.

Please don't think I'm being rude, but is your real name Thomas
'PointedEars' Lahn?

Steve Young (from my Thunderbird newsreader)

[toc] | [prev] | [next] | [standalone]


#25130

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2014-06-29 23:19 +0200
Message-ID<2459586.3RATVSoWxJ@PointedEars.de>
In reply to#25123
SteveYoungTbird wrote:

> On 06/28/2014 11:53 PM, Thomas 'PointedEars' Lahn wrote:
>>  [5] /…(?= [A-Z])/g (zero-length positive lookahead) does not appear to
>>      make sense when you want to match/filter words.  Why would you only
>>      match words that precede a word starting with a capital letter?
>>      What about multiple spaces, tabs, and newlines?
> 
> I am trying to identify German adjectives in a text. I thought that if I
> made an array of all the words that appeared before a noun (always
> capitalized in German) and then removed definite and indefinite
> articles, personal pronouns and other common words such as "von" etc I
> could then check the remaining words against an array of German
> adjectives. I would be grateful if someone could show me a better way.

Neither are all words adjectives that precede a capitalized word (e.g 
„Morgen geht es /ums/ Ganze.“ [approx. “It’ll be do or die tomorrow.”]); 
nor, because of variable word order, do all adjectives precede a noun in 
German (e.g. „Das Spiel heute war /spannend/.“ vs. “Heute war ein spannendes 
Spiel.” [“Today’s match was exciting.”/“It/there was an exciting match 
today.”]).

It is also insufficient to match only lowercase words because, although 
adjectives are usually written lowercase in German, too, proper names can 
contain capitalized adjectives (e.g. „Der /Fliegende/ Holländer“ [“The 
Flying Dutchman”], „Der /Elektrische/ Reporter“ [approx.: “The Electric 
Reporter”]), and nominalizations are common in German (often poetic or in an 
[recently, often misguided] attempt to avoid [seemingly] gender-specific 
forms, e.g. „der /Schlafende/“ [“the sleeper”], „die Studierenden“ [“the 
(university) students”]).

Syntax analysis is far more complex that you think, particularly that of 
German.  You appear to have an XY problem.

>> Please post using your real name.
> 
> Please don't think I'm being rude, but is your real name Thomas
> 'PointedEars' Lahn?

My real name is Thomas Lahn.  It is customary, at least on the Net, to 
insert the nickname in the real name like I do.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not Cc: me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#25098

FromJJ <jj4public@vfemail.net>
Date2014-06-27 19:31 +0700
Message-ID<uzip81820by1$.1s9nakgot7koy.dlg@40tude.net>
In reply to#25093
On Fri, 27 Jun 2014 09:17:43 +0200, SteveYoungTbird wrote:
> I have produced an array using:
> 
> var arr = [];
> arr = string.match(/(?:^| )([a-zäöüß]+)(?= [A-Z])/g);
> 
> This works as expected and the array is full and can be seen using
> console.log or alert().
> 
> The array consists of words which I need to filter, so I am trying to
> use .splice to remove unwanted instances of the same word using:
> 
> for (var i = arr.length - 1; i >= 0; i--) {
>     if (arr[i] === 'jim') {
>         arr.splice(i, 1);
>     }
> }
> 
> The for loop doesn't recognize any instances of, for instance, 'jim' in
> the array although there are several.
> 
> I tried the loop using an array I made myself and it worked fine, ie:
> 
> arr = ['jim', 'bob', 'arthur', 'jim', 'fred']
> 
> What is it about the array produced by the string.match that I am not
> understanding? Any help would be much appreciated.

It's just a normal array.
Are you sure the for loop actually succeeded? Cause if nothing matched, arr
would be null and arr.length would generate an error. And I don't see any
error handling.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web