473,725 Members | 1,740 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Perlish map() function

Perl's map() function is a powerful shortcut to accomplish many "loop over
an array and do X" operations.
Below is a quick hack to simulate similar functionality.
I've used it a few times and find it to be quite handy.
Any thoughts?

<script type="text/javascript">
function map(func) {
var i,j,o;
var results = [];
if (typeof(func)== "string") {
func = new Function('$_',f unc);
}
for (i=1; i<arguments.len gth; i++) {
o = arguments[i];
if (typeof(o)=="ob ject" && o.length) {
for (j=0; j<o.length; j++) {
results[results.length] = func(o[j]);
}
}
else if (typeof(o)=="ob ject") {
for (j in o) {
results[results.length] = func(o[j]);
}
}
else {
results[results.length] = func(o);
}
}
return results;
}
var o = { 'a':'a1', 'b':'b1', 'c':'c1' };
var a = [ 'a','b','c' ];

map( "alert($_)" , o , a, "test" );
map( function(o){ alert("Value:"+ o); } , o , a, "test" );
map( "alert($_); ", map( "return $_.toUpperCase( );" , o, a, "test") );
</script>

PS: The use of $_ as an identifier is carried over from Perl, in case you
aren't familiar with it.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 20 '06 #1
17 2018
Matt Kruse wrote:
Perl's map() function is a powerful shortcut to accomplish many "loop over
an array and do X" operations.
Below is a quick hack to simulate similar functionality.
I've used it a few times and find it to be quite handy.
Any thoughts?
Array.prototype .map() exists since JavaScript 1.6 (Gecko 1.8), you are
"too late" ;-)

Seriously, the application of your method seems more elegant for arbitrary
values than that of this built-in method (and your method is required in
JScript and JavaScript < 1.6 of course). I have included the (supposedly)
equivalent JavaScript 1.6 code below for completeness.
<script type="text/javascript">
function map(func) {
var i,j,o;
var results = [];
if (typeof(func)== "string") {
`typeof' is an operator, not a function:

if (typeof func == "string") {
func = new Function('$_',f unc);
}
for (i=1; i<arguments.len gth; i++) {
Since `i' is used only for this loop, I would declare it here:

for (var i = 1, len = arguments.lengt h; i < len; i++) {
o = arguments[i];
if (typeof(o)=="ob ject" && o.length) {
if (typeof o == "object" && o.length) {

Maybe one should test for o[0], too.
for (j=0; j<o.length; j++) {
var len;
for (j = 0, len = o.length; j < len; j++) {
results[results.length] = func(o[j]);
// since JavaScript 1.2, JScript 5.5
results.push(fu nc(o[j]));
}
}
else if (typeof(o)=="ob ject") {
for (j in o) {
results[results.length] = func(o[j]);
See above.
}
}
else {
results[results.length] = func(o);
See above.
}
}
return results;
}
var o = { 'a':'a1', 'b':'b1', 'c':'c1' };
var a = [ 'a','b','c' ];

map( "alert($_)" , o , a, "test" );
That would be in JavaScript 1.6:

Object.prototyp e.map = function(f)
{
for (var i in this)
{
if (i != 'map')
{
f(this[i]);
}
}
};

// do not inherit this from Object.prototyp e
// (else we handle each character of the string)
String.prototyp e.map = function(f)
{
f(this);
};

[o, a, "test"].map(
function(x)
{
x.map(function( y) { alert(y); });
});
map( function(o){ alert("Value:"+ o); } , o , a, "test" );
[o, a, "test"].map(
function(x)
{
x.map(function( y) { alert("Value:" + y); });
});
map( "alert($_); ", map( "return $_.toUpperCase( );" , o, a, "test") );
This one-liner becomes quite ugly with Array.prototype .map() only:

this.object_pro totype_map = Object.prototyp e.map;
Object.prototyp e.map = function(f)
{
for (var i in this)
{
if (i != 'map')
{
this[i] = f(this[i]);
}
}

return this;
};

this.string_pro totype_map = String.prototyp e.map;
String.prototyp e.map = function(f)
{
return f(this);
};

var a2 = [o, a, "test"].map(
function(x)
{
return x.map(
function(y)
{
return y.toUpperCase() ;
});
});

Object.prototyp e.map = this.object_pro totype_map;
delete this.object_pro totype_map;
String.prototyp e.map = this.string_pro totype_map;
delete this.string_pro totype_map;

a2.map(
function(x)
{
return x.map(
function(y)
{
alert(x);
});
});
[...]

Regards,
PointedEars
Feb 20 '06 #2
Thomas 'PointedEars' Lahn wrote:
Array.prototype .map() exists since JavaScript 1.6 (Gecko 1.8), you are
"too late" ;-)
I'm aware of this, but mine has more functionality, and isn't limited to
Arrays. (And can actually be used in a WWW context!)
Particularly, for my use, I often want to act on all items in an Object.
Also, I like being able to specify a quick and simple expression rather than
a full anonymous function.
if (typeof(func)== "string") {

`typeof' is an operator, not a function:


I know. But I just think typeof(obj) is clearer, so I always write it that
way.
if (typeof o == "object" && o.length) {
Maybe one should test for o[0], too.
I've actually revised it to this:
if ((typeof(o)=="o bject" && typeof(o.length )=="number" && (!Array || (o
instanceof Array)))) {
// since JavaScript 1.2, JScript 5.5
results.push(fu nc(o[j]));
Old habits die hard. Despite 1.2 being widespread enough to be assumed, I
tend to avoid using 1.2 array methods, since it doesn't hurt anything to do
it the old way. I suppose I should update my thinking.

mine:
map( function(o){ alert("Value:"+ o); } , o , a, "test" );


your example: [o, a, "test"].map(
function(x)
{
x.map(function( y) { alert("Value:" + y); });
});


I definitely think mine is easier to read! While the map() method in 1.6 is
no doubt useful, in general I think I would always prefer to use a method
like I've written. Which, btw, I've changed to:

function map(func) {
var i,j,o;
var results = [];
if (typeof(func)== "string") {
func = new Function('$_',f unc);
}
for (i=1; i<arguments.len gth; i++) {
o = arguments[i];
if ((typeof(o)=="o bject" && typeof(o.length )=="number" && (!Array || (o
instanceof Array)))) {
for (j=0; j<o.length; j++) {
results.push(fu nc(o[j]));
}
}
else if (typeof(o)=="ob ject" && (!Object || (o instanceof Object))) {
for (j in o) {
results.push(fu nc(o[j]));
}
}
else {
results.push(fu nc(o));
}
}
return results;
}

I found in testing that if I wanted to act on a group of Nodes, for example,
it would instead try to pull out its properties and act on each of those.
Thus the "instanceof Object" check.

Thanks for the constructive feedback.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 20 '06 #3
Matt Kruse wrote:
Thomas 'PointedEars' Lahn wrote:
Array.prototype .map() exists since JavaScript 1.6 (Gecko 1.8), you are
"too late" ;-)
I'm aware of this, but mine has more functionality, and isn't limited to
Arrays. (And can actually be used in a WWW context!)
Particularly, for my use, I often want to act on all items in an Object.
Also, I like being able to specify a quick and simple expression rather
than a full anonymous function.


See below.
if (typeof(func)== "string") {

`typeof' is an operator, not a function:


I know. But I just think typeof(obj) is clearer, so I always write it that
way.


I do not find it more clear because it makes it harder to see the method
calls. But maybe that is just me.
if (typeof o == "object" && o.length) {
Maybe one should test for o[0], too.


I've actually revised it to this:
if ((typeof(o)=="o bject" && typeof(o.length )=="number" && (!Array || (o
instanceof Array)))) {


`!Array' equals `false' always.
// since JavaScript 1.2, JScript 5.5
results.push(fu nc(o[j]));


Old habits die hard. Despite 1.2 being widespread enough to be assumed, I
tend to avoid using 1.2 array methods, since it doesn't hurt anything to
do it the old way. I suppose I should update my thinking.


Array.prototype .push() is supported _since_ JavaScript 1.2 (NN 4.0),
i.e. it is supported by all later versions. That it was introduced
in that particular JavaScript version matters only insofar that it
is not supported before the corresponding NN version.

Whether you should update your thinking here or not mostly depends
on whether you want to support IE 5.0 and older or not. Iff the
MSDN Library is correct about the JScript version here.
mine:
map( function(o){ alert("Value:"+ o); } , o , a, "test" );

your example:
[o, a, "test"].map(
function(x)
{
x.map(function( y) { alert("Value:" + y); });
});


I definitely think mine is easier to read! While the map() method in 1.6
is no doubt useful, in general I think I would always prefer to use a
method like I've written.


I did say quite the same, did I not?
[...]
Thanks for the constructive feedback.


You are welcome.
PointedEars
Feb 20 '06 #4
Matt Kruse wrote:
Thomas 'PointedEars' Lahn wrote:
Array.prototype .map() exists since JavaScript 1.6 (Gecko 1.8), you are
"too late" ;-)
I'm aware of this, but mine has more functionality, and isn't limited to
Arrays. (And can actually be used in a WWW context!)
Particularly, for my use, I often want to act on all items in an Object.


And you're most definitely not alone. Worse yet, in Javascript if
you've dared to augment the Object prototype, you'll in all likelihood
often end up with:

for (j in Obj) {
if ( Obj.hasOwnprope rty(j)) {

}
}

which can become irksome, tiresome and untidy. For me, that lead to
creation of an Object.prototyp e.Do function that, in parameterizatio n
and in body, is almost identical to your Perl 'map' function emulation.
That object-oriented prototypical approach seems to me to more in
keeping with the Javascript programming paradigm.

However, if your goal is to to provide an emulation of Perl
capabilities within Javascript, that's a bit of a different matter, and
your choice. But it's really not something I personally would find
myself particularly keen on (even speaking as one who used to be
somewhat attached to Perl as a scripting language). I'd much rather see
extended capabilities included under the model provided by the
language, as opposed to creating some sort of graft that doesn't
necessarily fit well. It sounds to me like a perfectly good way to end
up with a camel rather than a horse. ;-)
Also, I like being able to specify a quick and simple expression rather than
a full anonymous function.
if (typeof(func)== "string") {

`typeof' is an operator, not a function:


I know. But I just think typeof(obj) is clearer, so I always write it that
way.


Somewhat curiously, though, you don't find a similar need to be
"clearer" when using 'instanceof' ? ;-)

../rh

Feb 21 '06 #5
ro********@gmai l.com wrote:
For me, that lead to
creation of an Object.prototyp e.Do function that, in parameterizatio n
and in body, is almost identical to your Perl 'map' function
emulation. That object-oriented prototypical approach seems to me to
more in keeping with the Javascript programming paradigm.


However, you then need to extend the Array prototype, String prototype, etc.
I prefer map to look like a built-in command. Personal preference, I
suppose.
I know. But I just think typeof(obj) is clearer, so I always write
it that way.

Somewhat curiously, though, you don't find a similar need to be
"clearer" when using 'instanceof' ? ;-)


No, because this:

(typeof obj == "string")

isn't as obvious about order of operations as this:

(typeof(obj)==" string")
or
(obj instanceof Object)

I also always write:

if (condition) {
statement;
}

over:

if (condition)
statement;

because I think clarity is more important than brevity.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 21 '06 #6
Thomas 'PointedEars' Lahn wrote:
`!Array' equals `false' always.


Even prior to js1.2? I don't remember exactly, but I recall writing the
syntax of

if (!Array && (obj instanceof Array))

quite a long time ago, to protect against browsers which didn't have Array
defined.
I may very well be in error, though.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 21 '06 #7
Matt Kruse wrote:
ro********@gmai l.com wrote:
For me, that lead to
creation of an Object.prototyp e.Do function that, in parameterizatio n
and in body, is almost identical to your Perl 'map' function
emulation. That object-oriented prototypical approach seems to me to
more in keeping with the Javascript programming paradigm.
However, you then need to extend the Array prototype, String prototype, etc.


That, of course, is not the case. But even if so, what is your point --
that you shouldn't prototype in a prototypal language?
I prefer map to look like a built-in command. Personal preference, I
suppose.


I suppose. Somewhat unfortunate, in that it doesn't appear that you've
really considered other options that could possibly provide better
facility and be delivered with improved integration within the
language.
I know. But I just think typeof(obj) is clearer, so I always write
it that way.

Somewhat curiously, though, you don't find a similar need to be
"clearer" when using 'instanceof' ? ;-)


No, because this:

(typeof obj == "string")

isn't as obvious about order of operations as this:

(typeof(obj)==" string")
or
(obj instanceof Object)

I also always write:

if (condition) {
statement;
}

over:

if (condition)
statement;

because I think clarity is more important than brevity.


That latter is commendable, whereas I can't say the same for the
concious act of attempting to couch a prefix operator as a function in
the name of clarity. If indication or specification of order is
necessary in an expression, that's normally done by parenthetical
grouping, but not the one you use.

You did ask for comment, by the way. ;-)

... Ron

Feb 21 '06 #8
VK

ro********@gmai l.com wrote:
... is commendable, whereas I can't say the same for the
concious act of attempting to couch a prefix operator as a function in
the name of clarity. If indication or specification of order is
necessary in an expression, that's normally done by parenthetical
grouping, but not the one you use.


JavaScript 1.3 Language Reference, Netscape Corp. 1999

The typeof operator is used in either of the following ways:

1. typeof operand
2. typeof(operand)

The parentheses are optional.
The void operator is used in either of the following ways:

1. void(expression )
2. void expression
The parentheses surrounding the expression are optional, but it is good
style to use them.

So it *was* good style for typeof either. It even was specially
mentioned and accounted in ECMAScript specs. Again if something *was*
good style in 1998-1999 doesn't have to be good style in 2006. Fashions
for code "layout" change like dress fashions :-)
I personally still use typeof(obj) unless posting in clj : only to not
get kicks at least fot this one :-)

Still as this type of coding has a very long tradition and as it is
clearly described in ECMAScript I would move this question out of the
"code quality" category. It's merely the same issue as the evelasting
discussion where to place brakets:

function f() {
}

or

function f()
{
}

Feb 21 '06 #9
ro********@gmai l.com wrote:
However, you then need to extend the Array prototype, String
prototype, etc. That, of course, is not the case.


Well, then, you'll internally examine and switch logic depending on the
actual object.
In general, I think that extending the Object prototype is not the best
approach because it gets applied so widely.
But even if so, what is your point
-- that you shouldn't prototype in a prototypal language?
No, just that in this case it doesn't seem to make anything easier.
What if, for example, I want to call map() on 5 static values, like

map( "alert($_); " , 'a','b','c','d' ,'e' );

Doing this by extending Object() would be a pain and counter-intuitive, IMO.
I suppose. Somewhat unfortunate, in that it doesn't appear that
you've really considered other options that could possibly provide
better facility and be delivered with improved integration within the
language.


I've considered other options - in fact, Pointy Boy posted an example of how
to implement it with prototypes. The end result was messy, IMO.

--
Matt Kruse
http://www.JavascriptToolbox.com
http://www.AjaxToolbox.com
Feb 21 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
1284
by: gabriele renzi | last post by:
Hi gurus and nubys, matz said more than once that the perlish global variables like $/ or $: are going away in future releases. I wonder if is there already a decision, what they will become? I mean, it's easy to think that $DEFAULT_INPUT may become a class variable of IO but what about $1..$n or $: ? More, would it be possible to have some kind of backward compat via an
181
8844
by: Tom Anderson | last post by:
Comrades, During our current discussion of the fate of functional constructs in python, someone brought up Guido's bull on the matter: http://www.artima.com/weblogs/viewpost.jsp?thread=98196 He says he's going to dispose of map, filter, reduce and lambda. He's going to give us product, any and all, though, which is nice of him.
5
2151
by: amit kumar | last post by:
I am calling a function which returns pointer to a map. The declaration of the map is map<int,vectxyz*>. vectxyz is a vector containing pointer to a class xyz. For map<int,vectxyz*>* p1 In the called function, I am using p1->find(1) which is returning a valid iterator and not going to the end. I am returning p1 from the called function. But in the calling function, find(1) is going to the end, i.e unable to find the key 1, which was...
1
3552
by: Saeed Amrollahi | last post by:
Dear All C++ Programmers Hello I am Saeed Amrollahi. I am a software engineer in Tehran Sewerage Company. I try to use std::map and map::find member function. I use Visual Studio .NET. my program uses two MFC classes: CRect and CPoint which represents Rectangle and Point concepts (as usual) and a user
13
9673
by: kamaraj80 | last post by:
Hi I am using the std:: map as following. typedef struct _SeatRowCols { long nSeatRow; unsigned char ucSeatLetter; }SeatRowCols; typedef struct _NetData
0
1893
by: windandwaves | last post by:
Hi Folk Some of you may find this function useful. It makes it easier to create maps using Google Maps. I link it to a database of points. The main use of the function is that it creates all the javascript needed for Google maps to work. Any questions or comments? Please ask. Nicolaas
4
1970
windows_mss
by: windows_mss | last post by:
When I Select Source & Destination Dynamically, Path Getting Scatter Across The Map... hi, i can able to get the Correct Route and Path for the corresponding Source and destination, like this, map.GetRoute('Redmond, Washington, United States','seattle, Washington, United States',VEDistanceUnit.KiloMeter,VERouteType.Shortest);
8
2455
by: jayaramganapathy | last post by:
Hello friends, I have a map like std::map< std::string , std::map<std::string, std::string>* EpPropCache::propertyCache ; (This is a static instance and taken from *.cpp file) As you can see the value is a pointer to another map. I do new of std::map<std::string, std::stringand add the pointer to the map. Do I have to delete the map objects which I create with new , which I
5
3971
by: S S | last post by:
Hi I have a requirement where I am declaring a map within a class. class abc { map <void*, void*mMap; // I do not pass compare struct here. .... }; Here I am not passing compare function, but I want to do it into the
0
8872
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8747
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9246
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9162
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9091
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8069
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4773
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3211
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2150
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.