473,378 Members | 1,122 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Perl-Python-a-Day: one-liner loop Functional Style

One-Liner Loop in Functional Style

Xah Lee, 200510

Today we show a example of a loop done as a one-liner of Functional
Programing style.

Suppose you have a list of file full paths of images:

/Users/t/t4/oh/DSCN2059m-s.jpg
/Users/t/t4/oh/DSCN2062m-s.jpg
/Users/t/t4/oh/DSCN2097m-s.jpg
/Users/t/t4/oh/DSCN2099m-s.jpg
/Users/t/Icons_dir/icon_sum.gif

For those ending with -s (indicate a smaller version), you want to
change it to the full version without the -s, if it exists. Here's the
code:

# -*- coding: utf-8 -*-
# python

import re, os.path

imgPaths=[u'/Users/t/web/Periodic_dosage_dir/lanci/t4/oh/DSCN2059m-s.jpg',
u'/Users/t/web/Periodic_dosage_dir/lanci/t4/oh/DSCN2062m-s.jpg',
u'/Users/t/web/Periodic_dosage_dir/lanci/t4/oh/DSCN2097m-s.jpg',
u'/Users/t/web/Periodic_dosage_dir/lanci/t4/oh/DSCN2099m-s.jpg',
u'/Users/t/web/Icons_dir/icon_sum.gif']
# change the image path to the full sized image, if it exists
# that is, if image ends in -s.jpg, find one without the '-s'.
imgPaths2=[]
for myPath in imgPaths:
p=myPath
(dirName, fileName) = os.path.split(myPath)
(fileBaseName, fileExtension)=os.path.splitext(fileName)
if(fileBaseName[-2:] == '-s'):
p2=os.path.join(dirName,fileBaseName[0:-2]) + fileExtension
if os.path.exists(p2): p=p2
imgPaths2.append(p)

print imgPaths2

But how do you do it in a functional programing style? Namely,
something of the from imgPath2=f(imgPath), where the f is some
function. Normally, the f would be a pure function construct made up on
the spot, that is, lambda. But Python's lambda is limited to only a
expression as its body. Nevertheless, one can achieve a functional
style with some workaround, using map twice. Here's the code:

imgPaths3 = map( lambda x: os.path.exists(x[1]) and x[1] or x[0], \
map(lambda x: (x, re.sub( r"^(.+?)-s(\.[^.]+)$",r"\1\2", x)),
imgPaths))

The first map:

newList = map(lambda x: (x, re.sub( r"^(.+?)-s(\.[^.]+)$",r"\1\2", x)),
imgPaths)

generate a list of pairs (x, y), where x is the same element in
imgPaths, and y is one without the -s. Then, a second map:

map( lambda x: os.path.exists(x[1]) and x[1] or x[0], newList,
imgPaths))

checks if the path y exists, if so, use that, else, use the x part. The
function body is essentially of a conditional EXPRESSION, of the from
(test, if true return result1, else return result2). This form of a
test that returns a expression is very important in functional
programing. Because, in functional programing a common pattern is to
sequence functions and passing values. One cannot stop in the middle
and use a block structure. Here's how this form's syntax in several
languages:

test? trueExpression: falseExpression (C, Perl)
If[test, trueExpression, falseExpression] (Mathematica)
(test trueExpression falseExpression) (LISP)

In Python, there's no such form for this, but a semantically equivalent
workaround is to sequence boolean expressions as used in our example.
Namely:

test and trueExpression or falseExpression (Python)

This works because it exploits a particular behavior of how Python
treats boolean sequences. In Python, “x and y” returns y ifx is
true. And, “x or y” returns x if x is true. This behavior is
compatible with the mathematical sense of booleans. For example,
mathematically “x and y” should be true if both are true, yet in
Python if x is true then y is returned, and if y is true then this is
compatible with the math sense, but if y is false then the whole result
is also false, so it also satisfies the math sense. Similar is the case
of “x or y”. The point here is that one of the element is returned,
instead of a real True or False value. Therefore, in a twisted way this
can be used for the If[test, trueExpression, falseExpression] form.
Example.

result1= True and 4 or 5 # returns 4
result2= False and 4 or 5 # returns 5

print result1
print result2

Such language behavior is a result of the laziness of the compiler
implementation, particular seen in unix shells (&& and ||). The problem
with this design is that codes relying on the the returned element of a
boolean sequence does not clearly indicate the programer's intention.
It works by language pecularities, instead of expressed program logic.

For the official doc on evaluating booleans, see:
http://python.org/doc/2.4.2/lib/boolean.html

Here's the Perl code of the same loop block:

# perl
use File::Basename;

@imgPaths=(
'/Users/t/web/Periodic_dosage_dir/lanci/t4/oh/DSCN2059m-s.jpg',
'/Users/t/web/Periodic_dosage_dir/lanci/t4/oh/DSCN2062m-s.jpg',
'/Users/t/web/Periodic_dosage_dir/lanci/t4/oh/DSCN2097m-s.jpg',
'/Users/t/web/Periodic_dosage_dir/lanci/t4/oh/DSCN2099m-s.jpg',
'/Users/t/web/Icons_dir/icon_sum.gif');

# change the image path to the full sized image, if it exists
# that is, if image ends in -s.jpg, find one without the '-s'.
$imgPaths2=();
for $myPath (@imgPaths){
$p=$myPath;
($fileBaseName, $dirName, $fileExtension) = fileparse($myPath,
('\.[^.]+$') );
if (substr($fileBaseName,-2,2) eq '-s') {
$p2= $dirName . '/' .
substr($fileBaseName,0,length($fileBaseName)-2) . $fileExtension;
print $p2, "\n";
if (-e $p2) { $p=$p2}
}
push(@imgPaths2,$p);
}

use Data::Dumper;
print Dumper(\@imgPaths2)

In Perl, this can be written in a functional style one-liner:

@imgPaths3= map{
$y = $_;
$y =~ s/^(.+?)-s(\.[^.]+)$/$1$2/;
-e $y ? $y : $_;
} @imgPaths;

For the official doc of Perl's map, type in command line: “perldoc -f
map”
------
this article is archived at:
http://xahlee.org/perl-python/one-liner_loop.html

Xah
xa*@xahlee.org
http://xahlee.org/

Oct 20 '05 #1
0 2239

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

Similar topics

16
by: MetalOne | last post by:
1) def f(xs): for x in xs: if test(x): return True return False I know that I can do (2), but it operates on the whole list and the original may break out early. I want the efficiency of...
30
by: Christian Seberino | last post by:
How does Ruby compare to Python?? How good is DESIGN of Ruby compared to Python? Python's design is godly. I'm wondering if Ruby's is godly too. I've heard it has solid OOP design but then...
176
by: Thomas Reichelt | last post by:
Moin, short question: is there any language combining the syntax, flexibility and great programming experience of Python with static typing? Is there a project to add static typing to Python? ...
18
by: barry | last post by:
I'm having a problem creating a delay before each list item gets moved ( http://www.polisource.com/PublicMisc/list-splitter-timeout-bug.html ). Choose any number of columns, vertical layout, and...
1
by: petermichaux | last post by:
Hi, I have a general JavaScript library API design question based on some examples I have seen. There seem to be two options The first option is used by the AJAX libraries and by Matt Kruse's...
13
by: Sarath | last post by:
What's the advantage of using for_each than the normal iteration using for loop? Is there any 'tweak' to use stream objects as 'Function' parameter of for_each loop. Seems copy function can do...
15
by: Lorenzo Stella | last post by:
Hi all, I haven't experienced functional programming very much, but now I'm trying to learn Haskell and I've learned that: 1) in functional programming LISTS are fundmental; 2) any "cycle" in FP...
23
by: Sacred Heart | last post by:
Hi, I'm new to Python and have come across a problem I don't know how to solve, enter com.lang.python :) I'm writing some small apps to learn the language, and I like it a lot so far. My...
3
by: Gianni Mariani | last post by:
So I was put straight that double(v) is the same as (double)(v) recently and I'm somewhat surprised. I'm not the only one. I think T(V) should have exactly the same semantics as...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

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.