By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,910 Members | 1,077 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,910 IT Pros & Developers. It's quick & easy.

Updating string/array items

P: n/a
Hi --

I'm not entirely familiar with the norms and standard libraries of
JavaScript so if the answer to this is yesterday's news, please ignore.

I'm trying to write a simple text formatting function to make headings
proper case -- i.e. first letter of words capitalized.

I first tried this...

function inProperCase(s)
{
var result, i, k;

i = 0; result = s.toLowerCase();

while ((k = result.indexOf(' ', i)) -1) {
if (k - i 0) {
result[i] = result[i].toUpperCase();
}
i = k + 1;
}

if (result.length - i 1) {
result[i] = result[i].toUpperCase();
}

return result;
}

...but it didn't work. To my amazement, you cannot set a character in a
string by accessing that character with an index, like so:

s[i] = ch;

Must be because JavaScript strings are "Immutable" or "EtchedInStone" or
something. (Just kidding, no flames, please. I'm sure it is more
efficient.)

The only thing I could come up with was this (with some details, like the
"compound" while predicate, modified into a more readable form after being
called a "C-bigot" by a friend :)) which seems pretty heavy-handed with all
the string slicing and concatting:

function inProperCase(s)
{
var result = s.toLowerCase(),
i = 0, k = result.indexOf(' ', i);

while (k -1) {
if (k - i 0) {
result = result.substring(0, i) +
result[i].toUpperCase() +
result.substring(i+1, result.length);
}
i = k + 1;
k = result.indexOf(' ', i);
}

if (result.length - i 1) {
result = result.substring(0, i) +
result[i].toUpperCase() +
result.substring(i+1, result.length);
}

return result;
}

You call this as...

inProperCase(" madam i'm adam ");

...and you get...

" Madam I'm Adam "

Any suggestions for making this a bit more elegant?

BTW You may point me to a "library" with a super-efficient implementation
of this function, but that is not the point. My issue is, how do we update
single characters in a string (or single items in an array) in JavaScript?
Is it something like...

s.wouldYouCareToUpdateThisChar(i, ch); // :D (just kidding, calm
down...)

-or-

s.setCharAt(i, ch);

?
Thanks!

-- Ken
--
Message posted using http://www.talkaboutprogramming.com/...ng.javascript/
More information at http://www.talkaboutprogramming.com/faq.html

Oct 16 '07 #1
Share this Question
Share on Google+
20 Replies


P: n/a
Xcriber51 a pensé très fort :
Hi --

I'm not entirely familiar with the norms and standard libraries of
JavaScript so if the answer to this is yesterday's news, please ignore.

I'm trying to write a simple text formatting function to make headings
proper case -- i.e. first letter of words capitalized.

I first tried this...

function inProperCase(s)
{
var result, i, k;

i = 0; result = s.toLowerCase();

while ((k = result.indexOf(' ', i)) -1) {
if (k - i 0) {
result[i] = result[i].toUpperCase();
}
i = k + 1;
}

if (result.length - i 1) {
result[i] = result[i].toUpperCase();
}

return result;
}

..but it didn't work. To my amazement, you cannot set a character in a
string by accessing that character with an index, like so:

s[i] = ch;

Must be because JavaScript strings are "Immutable" or "EtchedInStone" or
something. (Just kidding, no flames, please. I'm sure it is more
efficient.)

The only thing I could come up with was this (with some details, like the
"compound" while predicate, modified into a more readable form after being
called a "C-bigot" by a friend :)) which seems pretty heavy-handed with all
the string slicing and concatting:

function inProperCase(s)
{
var result = s.toLowerCase(),
i = 0, k = result.indexOf(' ', i);

while (k -1) {
if (k - i 0) {
result = result.substring(0, i) +
result[i].toUpperCase() +
result.substring(i+1, result.length);
}
i = k + 1;
k = result.indexOf(' ', i);
}

if (result.length - i 1) {
result = result.substring(0, i) +
result[i].toUpperCase() +
result.substring(i+1, result.length);
}

return result;
}

You call this as...

inProperCase(" madam i'm adam ");

..and you get...

" Madam I'm Adam "

Any suggestions for making this a bit more elegant?

BTW You may point me to a "library" with a super-efficient implementation
of this function, but that is not the point. My issue is, how do we update
single characters in a string (or single items in an array) in JavaScript?
Is it something like...

s.wouldYouCareToUpdateThisChar(i, ch); // :D (just kidding, calm
down...)

-or-

s.setCharAt(i, ch);

?
Thanks!

-- Ken
take a look at this

http://www.codeproject.com/jscript/propercase.asp

// proper case function (JScript 5.5+)
function toProperCase(s)
{
return s.toLowerCase().replace(/^(.)|\s(.)/g,
function($1) { return $1.toUpperCase(); });
}
Oct 16 '07 #2

P: n/a
On Oct 16, 4:29 pm, matatunos <matatu...@gmail.comwrote:
Xcriber51 a pensé très fort :
<snip>
>I'm trying to write a simple text formatting function to make
headings proper case -- i.e. first letter of words capitalized.
<snip>
>..but it didn't work. To my amazement, you cannot set a
character in a string by accessing that character with
an index, like so:
> s[i] = ch;
Being able to read a single character from a string in such a way is
not standardised and not universally supported. Use:-

var ch = s.charAt(i);

- to read individual characters from a string.
>Must be because JavaScript strings are "Immutable" ...
<snip>

Yes they are. You cannot change a string value, only replace it with a
new one.
take a look at this

http://www.codeproject.com/jscript/propercase.asp

// proper case function (JScript 5.5+)
function toProperCase(s)
{
return s.toLowerCase().replace(/^(.)|\s(.)/g,
function($1) { return $1.toUpperCase(); });
}
It doesn't work particularly well. Given:-

toProperCase('this is very odd indeed')

The output is:-

"This Is very Odd indeed"

- which is hardly "proper" case.

Oct 16 '07 #3

P: n/a
On Oct 16, 9:15 pm, Henry <rcornf...@raindrop.co.ukwrote:
It doesn't work particularly well. Given:-

toProperCase('this is very odd indeed')

The output is:-

"This Is very Odd indeed"

- which is hardly "proper" case.
We just need to replace the \s with \s+ and things should work out to
be fine.

function toProperCase(s)
{
s.toLowerCase().replace(/^(.)|\s+(.)/g,
function($1) { return $1.toUpperCase(); });
}

The output of "toProperCase('this is very odd indeed')" is "This
Is Very Odd Indeed".

/^STS$/

Oct 16 '07 #4

P: n/a
On Oct 16, 6:33 pm, getsanjay.sha...@gmail.com wrote:
On Oct 16, 9:15 pm, Henry wrote:
It doesn't work particularly well. Given:-
>toProperCase('this is very odd indeed')
>The output is:-
>"This Is very Odd indeed"
>- which is hardly "proper" case.

We just need to replace the \s with \s+ and things should
work out to be fine.
We?

It would be better to replace the dots with something that excluded
whitespace characters, such as /S.
function toProperCase(s)
{
s.toLowerCase().replace(/^(.)|\s+(.)/g,
function($1) { return $1.toUpperCase(); });

}

The output of "toProperCase('this is very odd indeed')" is "This
Is Very Odd Indeed".
It still fails to uppercase the fist letter in:-

toProperCase(' this is very odd indeed');
var toProperCase2 = (function(){
var rx = /^\S|\s\S/g;
function replacer(a){
return a.toUpperCase();
};
return (function(s){
return s.toLowerCase().replace(rx, replacer);
});
})();

Oct 16 '07 #5

P: n/a
pr
Evertjan. wrote:
return this.toLowerCase().replace(/(\b\w)/g,
In English, I agree. But "éléphant" gives "éLéPhant".
Oct 16 '07 #6

P: n/a
pr wrote on 16 okt 2007 in comp.lang.javascript:
Evertjan. wrote:
>return this.toLowerCase().replace(/(\b\w)/g,

In English, I agree. But "éléphant" gives "éLéPhant".
O'Brian won't be happy too, pr.

It is impossible to provide for all minor languages.

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
Oct 16 '07 #7

P: n/a
pr
Evertjan. wrote:
pr wrote on 16 okt 2007 in comp.lang.javascript:
>Evertjan. wrote:
>>return this.toLowerCase().replace(/(\b\w)/g,
In English, I agree. But "éléphant" gives "éLéPhant".

O'Brian won't be happy too, pr.
replace(/(^\S|[\s'\u2019]\S)/g, ...

:-)
>
It is impossible to provide for all minor languages.
That'll upset the French.
Oct 16 '07 #8

P: n/a
pr wrote on 16 okt 2007 in comp.lang.javascript:
Evertjan. wrote:
>pr wrote on 16 okt 2007 in comp.lang.javascript:
>>Evertjan. wrote:
return this.toLowerCase().replace(/(\b\w)/g,
In English, I agree. But "éléphant" gives "éLéPhant".

O'Brian won't be happy too, pr.

replace(/(^\S|[\s'\u2019]\S)/g, ...

:-)
>>
It is impossible to provide for all minor languages.
That'll upset the French.
O'Brian French?????
--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
Oct 16 '07 #9

P: n/a
pr
Evertjan. wrote:
pr wrote on 16 okt 2007 in comp.lang.javascript:
>Evertjan. wrote:
>>pr wrote on 16 okt 2007 in comp.lang.javascript:

Evertjan. wrote:
return this.toLowerCase().replace(/(\b\w)/g,
In English, I agree. But "éléphant" gives "éLéPhant".
O'Brian won't be happy too, pr.
replace(/(^\S|[\s'\u2019]\S)/g, ...

:-)
>>It is impossible to provide for all minor languages.
That'll upset the French.

O'Brian French?????

No, éléphant is French.
Oct 16 '07 #10

P: n/a
pr wrote on 16 okt 2007 in comp.lang.javascript:
Evertjan. wrote:
>pr wrote on 16 okt 2007 in comp.lang.javascript:
>>Evertjan. wrote:
pr wrote on 16 okt 2007 in comp.lang.javascript:

Evertjan. wrote:
>return this.toLowerCase().replace(/(\b\w)/g,
In English, I agree. But "éléphant" gives "éLéPhant".
O'Brian won't be happy too, pr.
replace(/(^\S|[\s'\u2019]\S)/g, ...

:-)

It is impossible to provide for all minor languages.

That'll upset the French.

O'Brian French?????

No, éléphant is French.
Je ne comprend pas, mon vieux pr [m/f].

There are pas des éléphants in France, in the wild that is, I hope,
but even in the Kales [Calais] directory, on trouve two O'Brians.

<http://www.pagesjaunes.fr/trouverunnom/RecherchePagesBlanches.do>

btw, would a French O'Brian rhyme with Chateaubriand?

Getting OT really!

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
Oct 17 '07 #11

P: n/a
Thanks for all the tips, guys. And I appreciate the sense of humor, too.
But I'm still in the dark on what I specifically asked about: how do we
deal with updating single characters in a string?

Using some library references, I was able to gather this (probably
dubious) insight. I use conversion routines to read the characters into an
array and vice versa (ugly)...

function charsOf(s)
{
var buff = new Array();
for (var i = 0; i<s.length; i++) {buff[i] = s.charAt(i);}

return buff;
}

function stringOf(buff)
{
return buff.join("");
}
...then I use that do something with specific characters.
function charUpdate(s)
{
var buff = charsOf(s);
// a totally arbitrary operation
buff[0] = String.fromCharCode(s.charCodeAt(0) - 4);

// too bad I can't write
// buff[0] = buff[0] - 4;

return stringOf(buff);
}

When you call this with...

charUpdate("ember")

...you get...

"amber"

etc.

Is this (admittedly dinosoric, C-oriented) way the only way to deal with
this issue, or how many light years (or maybe "sound" years) am I backward
here?

Thanks!
-- Ken
--
Message posted using http://www.talkaboutprogramming.com/...ng.javascript/
More information at http://www.talkaboutprogramming.com/faq.html

Oct 17 '07 #12

P: n/a
OK, maybe you *can* deal with strings items as pure cars, like this:

function charsOf(s)
{
var buff = new Array();
for (var i = 0; i<s.length; i++) {buff[i] = s.charCodeAt(i);}
return buff;
}

function stringOf(buff)
{
for (var i = 0; i<buff.length; i++) {buff[i] =
String.fromCharCode(buff[i]);}
return buff.join("");
}

Then, combined with the very cool feature of dynamically adding functions
to a class's prototype, I can code:

String.prototype.asChars = function() {
return charsOf(this);
}

Array.prototype.asString = function() {
return stringOf(this);
}

...and use it as...

function charUpdate(s)
{
var buff = s.asChars();
// a totally arbitrary operation
buff[0] -= 4;

return buff.asString();
}

Yes, I know, you'll say "why bother with all this hassle when you can just
use the 'replace' function of the String class with regexes and
everything," and you'll be right. I just wanted to see how it would be
done. Who knows, could come in handy some time.

Thanks again.
-- Ken

--
Message posted using http://www.talkaboutprogramming.com/...ng.javascript/
More information at http://www.talkaboutprogramming.com/faq.html

Oct 17 '07 #13

P: n/a
Xcriber51 <Ken wrote:
OK, maybe you *can* deal with strings items as pure cars, like this:

function charsOf(s)
{
var buff = new Array();
for (var i = 0; i<s.length; i++) {buff[i] = s.charCodeAt(i);}
return buff;
}

function stringOf(buff)
{
for (var i = 0; i<buff.length; i++) {buff[i] =
String.fromCharCode(buff[i]);}
return buff.join("");
}

Then, combined with the very cool feature of dynamically adding functions
to a class's prototype, I can code:

String.prototype.asChars = function() {
return charsOf(this);
}

Array.prototype.asString = function() {
return stringOf(this);
}

..and use it as...

function charUpdate(s)
{
var buff = s.asChars();
// a totally arbitrary operation
buff[0] -= 4;

return buff.asString();
}

Yes, I know, you'll say "why bother with all this hassle when you can just
use the 'replace' function of the String class with regexes and
everything," and you'll be right. I just wanted to see how it would be
done. Who knows, could come in handy some time.
Indeed. One of te greatest strengths of C as a language versus stuff
like Pascal,was that while strongly type, you could in fact break the
rules comprehensively and explicitly.

When faced with a random string, in which the first byte identifies what
class it is, the next two how long it is, the fourth a bit field giving
further details on what was inside it, and the next few a random
collection of data values, sometimes not aligned on byte boundaries at
all, Pascal is a complete nightmare: In C you just using a roving
pointer and a load of casts to split it up into what you want.

Such strings are very common in comms type programming or interfacing
with instrumentation. Or indeed disk systems at low level.

Its nice to know that at least Javashite has left the door open. Pascal
needed a jemmy and a wedge to have a chance..

Thanks again.
-- Ken

--
Message posted using http://www.talkaboutprogramming.com/...ng.javascript/
More information at http://www.talkaboutprogramming.com/faq.html
Oct 17 '07 #14

P: n/a
pr
Xcriber51 <Ken wrote:
OK, maybe you *can* deal with strings items as pure cars, like this:

function charsOf(s)
{
var buff = new Array();
for (var i = 0; i<s.length; i++) {buff[i] = s.charCodeAt(i);}
return buff;
}

function stringOf(buff)
{
for (var i = 0; i<buff.length; i++) {buff[i] =
String.fromCharCode(buff[i]);}
return buff.join("");
}
Well you could, but it's a fearsome amount of work... As you asked for
in your previous post, here are two alternatives:

c = s.charCodeAt(5);
s = s.substring(0, 5) + String.fromCharCode(c - 4) + s.substring(6);

or

a = s.split("");
a[5] = String.fromCharCode(s.charCodeAt(5) - 4);
s = a.join("");
Then, combined with the very cool feature of dynamically adding functions
to a class's prototype, I can code:

String.prototype.asChars = function() {
return charsOf(this);
}
or:

function charsOf() {
var buff = new Array();
for (var i = 0; i < this.length; i++) { // note 'this'
buff[i] = this.charCodeAt(i);
}
return buff;
}

String.prototype.asChars = charsOf; // without brackets

or just define it anonymously.

Array.prototype.asString = function() {
return stringOf(this);
}

..and use it as...

function charUpdate(s)
{
var buff = s.asChars();
// a totally arbitrary operation
buff[0] -= 4;

return buff.asString();
}

Yes, I know, you'll say "why bother with all this hassle when you can just
use the 'replace' function of the String class with regexes and
Correct! ;-)
everything," and you'll be right. I just wanted to see how it would be
done. Who knows, could come in handy some time.
At the very least you've given yourself a few alternatives to choose from.
Thanks again.
Cheers.

Oct 17 '07 #15

P: n/a
Evertjan wrote:
pr wrote on 16 okt 2007 in comp.lang.javascript:
>Evertjan. wrote:
>>return this.toLowerCase().replace(/(\b\w)/g,
>In English, I agree. But "éléphant" gives "éLéPhant".

It is impossible to provide for all minor languages.
I'll put that statement on your account :)

But Swahili would qualify here as a major language, because it uses
ASCII only:
http://en.wikipedia.org/wiki/Western...uting)#History

On the other hand, Dutch would qualify here as a very minor language.
The both graphemic diphthong IJ-ligatures \u0132 and \u0133 aren't
even included in ISO/IEC 8859, which covers all European languages
plus Thai, Cyrillic, Arabic, etc:
http://en.wikipedia.org/wiki/ISO-8859

--
Bart

Oct 17 '07 #16

P: n/a
Bart Van der Donck wrote on 17 okt 2007 in comp.lang.javascript:
Evertjan wrote:
>pr wrote on 16 okt 2007 in comp.lang.javascript:
>>Evertjan. wrote:
return this.toLowerCase().replace(/(\b\w)/g,
>>In English, I agree. But "éléphant" gives "éLéPhant".

It is impossible to provide for all minor languages.

I'll put that statement on your account :)

But Swahili would qualify here as a major language, because it uses
ASCII only:
http://en.wikipedia.org/wiki/Western..._(computing)#H
istory

On the other hand, Dutch would qualify here as a very minor language.
The both graphemic diphthong IJ-ligatures \u0132 and \u0133 aren't
even included in ISO/IEC 8859, which covers all European languages
plus Thai, Cyrillic, Arabic, etc:
http://en.wikipedia.org/wiki/ISO-8859
Ha-die-Bart,

By Dutch diphthongs you must mean Double Dutch?
--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
Oct 17 '07 #17

P: n/a
In comp.lang.javascript message <Xn********************@194.109.133.242>
, Tue, 16 Oct 2007 19:34:28, Evertjan. <ex**************@interxnl.net>
posted:
>>It is impossible to provide for all minor languages.
That'll upset the French.

O'Brian French?????
Well, he (Patrick) did live there.

<FAQENTRY>AISB, the FAQ is weak on RegExps. This topic would supply a
suitable example, perhaps presenting the simplest and the finest
solutions. I like the approach of your

String.prototype.toProper = function(){
return this.replace( /(\b\w)(\w*)/g ,
function(x,a,b){return a.toUpperCase()+b.toLowerCase();});
};

with a rearrangement of whitespace and a note about languages with
alphabets other than 26 A-Z.
For the OP : the simplest way may be to step character-by-character with
..charAt through the original string, noting whether the present
character is a letter and retaining one value of that in the next step,
and doing .toLowerCase or .toUpperCase accordingly before adding to what
has been processed so far.
But note that the test "Ban Ki-moon from RoK is S-G of the UN" could be
hard to pass by any method.

It's a good idea to read the newsgroup c.l.j and its FAQ. See below.

--
(c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v6.05 IE 6
news:comp.lang.javascript FAQ <URL:http://www.jibbering.com/faq/index.html>.
<URL:http://www.merlyn.demon.co.uk/js-index.htmjscr maths, dates, sources.
<URL:http://www.merlyn.demon.co.uk/TP/BP/Delphi/jscr/&c, FAQ items, links.
Oct 17 '07 #18

P: n/a
Evertjan." wrote:
By Dutch diphthongs you must mean Double Dutch?
It's not slang; those ligatures are recognized as official characters
(which doesn't mean they are often written otherwise). See section
2.1. of:
http://en.wikipedia.org/wiki/IJ_%28letter%29

Dutch diphthongs would be 'au', 'ij', 'ui', etc...
http://en.wikipedia.org/wiki/Diphthong

--
Bart

Oct 17 '07 #19

P: n/a
In comp.lang.javascript message <11****************@damia.uk.clara.net>,
Wed, 17 Oct 2007 15:58:11, The Natural Philosopher <a@b.cposted:
>
When faced with a random string, in which the first byte identifies
what class it is, the next two how long it is, the fourth a bit field
giving further details on what was inside it, and the next few a random
collection of data values, sometimes not aligned on byte boundaries at
all, Pascal is a complete nightmare: In C you just using a roving
pointer and a load of casts to split it up into what you want.
In Borland Pascal, one can match your C method; and one can also define
a suitable variant type to accommodate the rest. Well, not aligned on
byte boundaries is bad.

Without a RegExp, and ignoring alternative whitespace and odd alphabets
for simplicity, the following is simple and should be efficient (but
compare use of A with direct concatenation onto a string).

St = "banana plum cabbage"

for (J=0, L=St.length, xSpace=true, A = [] ; J<L ; J++) {
C = St.charAt(J) ; Space = C == " "
if (xSpace && ! Space) C = C.toUpperCase()
A.push(C) ; xSpace = Space }
A.join("")

There, && ! Space is for occasional efficiency.

--
(c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
Web <URL:http://www.merlyn.demon.co.uk/- FAQish topics, acronyms, & links.
Proper <= 4-line sig. separator as above, a line exactly "-- " (SonOfRFC1036)
Do not Mail News to me. Before a reply, quote with ">" or "" (SonOfRFC1036)

Oct 18 '07 #20

P: n/a
dh**********@gmail.com wrote:
Does JavaScript really have all unicode mappings?

http://www.unicode.org/Public/UNIDAT...#Case_Mappings
JavaScript since version 1.3 should have.

,-[ECMA-262 Ed. 1 and 2]
|
| 15.5.4.12 String.prototype.toUpperCase
|
| Returns a string equal in length to the length of the result of converting
| this object to a string. The result is a string value, not a string
| object.
|
| Every character of the result is equal to the corresponding character of
| the string, unless that character has a Unicode 2.0 uppercase equivalent,
| in which case the uppercase equivalent is used instead. (The canonical
| Unicode 2.0 case mapping shall be used, which does not depend on
| implementation or locale.)
|
| Note that the toUpperCase function is intentionally generic; it does not
| require that its `this' value be a string object. Therefore, it can be
| transferred to other kinds of objects for use as a method.

,-[ECMA-262 Ed. 3 Final]
|
| 15.5.4.18 String.prototype.toUpperCase()
|
| This function behaves in exactly the same way as
| String.prototype.toLowerCase, except that characters are mapped to their
| uppercase equivalents as specified in the Unicode Character Database.
|
| NOTE Because both toUpperCase and toLowerCase have context-sensitive
| behaviour, the functions are not symmetrical. In other words,
| s.toUpperCase().toLowerCase() is not necessarily equal to s.toLowerCase().
|
| NOTE The toUpperCase function is intentionally generic; it does not
| require that its `this' value be a String object. Therefore, it
| can be transferred to other kinds of objects for use as a method.
PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cls, <f8*******************@news.demon.co.uk>
Oct 22 '07 #21

This discussion thread is closed

Replies have been disabled for this discussion.