473,387 Members | 1,606 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,387 software developers and data experts.

Working with a list in a more „pythonic“ way

Hi all,

I would like to find a more pythonic way of solving the following:

Having a string consisting of letters only, find out the total sound
score of the string. The sound score is calculated as the sum of the
transition scores between the characters in that string. The transition
scores are stored in a 26 x 26 matrix. I.e. the transition A -> F would
have the score soundScoreMatrix[0][5].

I have come up with the following solution, but I hope some of you might
suggest a more _functional_ (reduce and map) way of diong it.

n = 0 # the final score of the string

for i in range(len(phrase)):
try:
n += soundScoreMatrix[ord(x[i]) - 65][ord(x[i + 1]) - 65]
except IndexError:
pass

I was thinking about using "reduce", but that would not work as the
input and output of the function I would use are different (string input,
integer output).

Many thanks in advance,
Nicky
Jul 18 '05 #1
12 1497
Nickolay Kolev wrote:
...The sum of transition scores between the characters in a string.
The transition scores are stored in a 26 x 26 matrix. I.e. the
transition A -> F would have the score soundScoreMatrix[0][5].
This is the part I'd change:

# Setup: transitionScore['AF'] = soundScoreMatrix[0][5].
transitionScore = {}
for i in range(26):
first = chr(65+i)
row = soundScoreMatrix[i]
for j in range(26):
transitionScore[first + chr(65+j)] = row[j]
n = 0 # the final score of the string
for i in range(len(phrase)):
try:
n += soundScoreMatrix[ord(x[i]) - 65][ord(x[i + 1]) - 65]
except IndexError:
pass


def scoreit(phrase):
score = 0
for i in range(len(phrase) - 1):
score += transitionScore.get(phrase[i : i+2], 0)
return score

But if you insist on a more functional style:

def scoreterse(phrase):
return sum([transitionScore.get(phrase[i : i+2], 0)
for i in range(len(phrase) - 1)])

which doesn't really look clearer to me. I'd be tempted to insert
a line:
phrase = phrase.upper()

at the top of the function (scoreit or scoreterse) you use, depending,
of course, on the reliability of the source of your data.

--
-Scott David Daniels
Sc***********@Acm.Org
Jul 18 '05 #2
il 4 Apr 2004 10:48:28 GMT, Nickolay Kolev <nm*****@uni-bonn.de> ha
scritto::

I have come up with the following solution, but I hope some of you might
suggest a more _functional_ (reduce and map) way of diong it.

n = 0 # the final score of the string

for i in range(len(phrase)):
try:
n += soundScoreMatrix[ord(x[i]) - 65][ord(x[i + 1]) - 65]
except IndexError:
pass

I was thinking about using "reduce", but that would not work as the
input and output of the function I would use are different (string input,
integer output).


why not? you just need to say to reduce to use a 0 as the first
parameter:

say:

def get_val(x):
# gets the value from SSMatrix, now dumb
return ord(x)
reduce(lambda a,b: a+get_val(b),list('blablabla'),0) #909

Jul 18 '05 #3
Nickolay Kolev wrote:
I was thinking about using "reduce", but that would not work as the
input and output of the function I would use are different (string input,
integer output).


reduce() does not impose such a restriction. Optimized for minimal
robustness and readability (but working, I hope, and functional in the
_narrow_ sense):

def calcScore(phrase):
return reduce(
lambda (sigma, last), i: (sigma + soundScoreMatrix[last][i], i),
map(lambda c: ord(c)-65, phrase[1:]), (0, ord(phrase[0])-65))[0]

Seriously, trying to apply a particular style does often result in bad
design. Either go with Scott Daniels' approach or debug your initial idea
to something that works. Both ways are more "pythonic" than the above.

Peter
Jul 18 '05 #4
> def get_val(x):
# gets the value from SSMatrix, now dumb
return ord(x)


The point is to sum the transitions *between* the characters and the
matrix only contains those scores. So "getting the value from SSMatrix"
for a single character makes no sense (and is impossible).

Nicky
Jul 18 '05 #5
> This is the part I'd change:

# Setup: transitionScore['AF'] = soundScoreMatrix[0][5].
transitionScore = {}
for i in range(26):
first = chr(65+i)
row = soundScoreMatrix[i]
for j in range(26):
transitionScore[first + chr(65+j)] = row[j]
That would create another list containing all possible transitions,
right? Are you doing this just to avoid indexing the matrix later when
going over the phrase letter by letter?
def scoreit(phrase):
score = 0
for i in range(len(phrase) - 1):
score += transitionScore.get(phrase[i : i+2], 0)
return score

But if you insist on a more functional style:

def scoreterse(phrase):
return sum([transitionScore.get(phrase[i : i+2], 0)
for i in range(len(phrase) - 1)])


It is just those *for i in range(len(x))* things I was hoping to get rid
of.

As mentioned, I have a solution that works and produces the expected
results. I wanted to see if there was a clearer way to write what I had
in mind. You see, writing the factorial function using "reduce" was a
breakthrough for me... :-)

Thanks for your reply!

Nicky
Jul 18 '05 #6
Nickolay Kolev <nm*****@uni-bonn.de> wrote in message news:<20********************@news.rhrz.uni-bonn.de>...

Having a string consisting of letters only, find out the total sound
score of the string. The sound score is calculated as the sum of the
transition scores between the characters in that string. The transition
scores are stored in a 26 x 26 matrix. I.e. the transition A -> F would
have the score soundScoreMatrix[0][5].


My attempt here:

import operator
soundScoreMatrix = [[.1,]*26]*26 # sample score matrix
phrase = 'abracadabra'
cap_phrase = phrase.upper()
indices = [ord(c)-65 for c in cap_phrase]
scores = [soundScoreMatrix[indices[i-1]][indices[i]]
for i in range(1, len(indices))]
sum = reduce(operator.add, scores)
print sum

regards,

Hung Jung
Jul 18 '05 #7

"Nickolay Kolev" <nm*****@uni-bonn.de> wrote in message
news:20********************@news.rhrz.uni-bonn.de...
I would like to find a more pythonic way of solving the following: .... I have come up with the following solution, but I hope some of you might
suggest a more _functional_ (reduce and map) way of diong it.


For anti-reduce Pythoneers, those two desires are contradictory;-) My
take: Pythonic is first correct, then about as clear as possible what is
being done and why that gives the correct answer. Both your table lookup
and Daniels dict lookup are immediately obvious and thus qualify to me.
Both handle the switch between chars and pairs of chars about as smoothly
as possible (except for your unnecessary try: except: as a substitute for
subtracting 1 from the length).

Rewritten, your code is

score = 0
for i in range(len(phrase)-1):
score += soundScoreMatrix[ord(x[i]) - 65][ord(x[i + 1]) - 65]

Once written thusly, the reduce form is obvious (but obviously not tested):

reduce(lambda score, i: score + soundScoreMatrix[ord(x[i]) - 65][ord(x[i +
1]) - 65],
range(len(phrase)-1), 0)

but aside from any didactic value this has, I prefer, in this case, the
written-out loop.

Terry J. Reedy


Jul 18 '05 #8
[second try, python.org refused the message when the header contained
non-ascii characters. As an aside, does anyone know how to configure
mutt to quote non-ascii characters in headers?]

First, you might want to map the letters to numbers all at once:
phrase = [ord(x) - 65 for x in phrase]
then you could use an iterator to give the pairs:
def pairs(seq):
seq = iter(seq)
a = seq.next()
for j in seq:
yield a, j
a = j
Example usage:
list(pairs(range(5)))

[(0, 1), (1, 2), (2, 3), (3, 4)]

So now you can write
n = 0
for first, second in pairs(phrase):
n += soundScore[first][second]
taking care of IndexError as above. You could also make soundScore a
dictionary, which I think was discussed elsewhere.
n = 0
for p in pairs(phrase):
n += soundScore.get(p, 0)
or
n = sum([soundScore.get(p, 0) for p in pairs(phrase)])

Jeff

Jul 18 '05 #9
In article <ma**************************************@python.o rg>,
"Terry Reedy" <tj*****@udel.edu> wrote:
Rewritten, your code is

score = 0
for i in range(len(phrase)-1):
score += soundScoreMatrix[ord(x[i]) - 65][ord(x[i + 1]) - 65]

Once written thusly, the reduce form is obvious (but obviously not tested):

reduce(lambda score, i: score + soundScoreMatrix[ord(x[i]) - 65][ord(x[i +
1]) - 65],
range(len(phrase)-1), 0)

but aside from any didactic value this has, I prefer, in this case, the
written-out loop.


I prefer the sum form -- if sum() isn't good for this example, what is
it there for at all? I also don't like seeing the magic number 65
without some sort of explanation. And how come you're using x in one
place and phrase in another?

ords = [ord(c) - ord('A') for c in phrase.upper()]
score = sum([soundScoreMatrix[ords[i]][ords[i+1]]
for i in range(len(phrase)-1)
if 0 <= ords[i] < 26 and 0 <= ords[i+1] < 26])

--
David Eppstein http://www.ics.uci.edu/~eppstein/
Univ. of California, Irvine, School of Information & Computer Science
Jul 18 '05 #10
Nickolay Kolev wrote:
I have come up with the following solution, but I hope some of you might
suggest a more _functional_ (reduce and map) way of diong it.

n = 0 # the final score of the string

for i in range(len(phrase)):
try:
n += soundScoreMatrix[ord(x[i]) - 65][ord(x[i + 1]) - 65]
except IndexError:
pass

I was thinking about using "reduce", but that would not work as the
input and output of the function I would use are different (string input,
integer output).

IMO, the clearest functional way to do it (where, for the sake of
argument, we're defining functional not to include list comps) is to
use offset slices. The idea is to use one slice of phrase to
represent the first index, and a second slice, offset by one, to
represent the second index in the matrix. I'd also map the phrase
into integers beforehand. Take a look:

iphrase = map(lambda x:ord(x)-65,phrase)
n = sum(map(lambda a,b: soundScoreMatrix[a][b], iphrase[:-1], iphrase[1:]))

If you want to use reduce instead of sum (say you're not yet at Python
2.3), then replace "sum(x)" with "reduce(operator.add,x)".
--
CARL BANKS http://www.aerojockey.com/software
"If you believe in yourself, drink your school, stay on drugs, and
don't do milk, you can get work."
-- Parody of Mr. T from a Robert Smigel Cartoon
Jul 18 '05 #11
Peter Otten <__*******@web.de> wrote in message news:<c4*************@news.t-online.com>...

def calcScore(phrase):
return reduce(
lambda (sigma, last), i: (sigma + soundScoreMatrix[last][i], i),
map(lambda c: ord(c)-65, phrase[1:]), (0, ord(phrase[0])-65))[0]


That's it! Great! "Tail call" in functional programming for emulating
loop variables in imperative programming (the "last" variable in this
case.) However, whenever functional languages get to the point of
using tail calls, I think they get into a sad state of affair. It's
basically using functional language to do imperative programming. In
imperative languages you would have a sequence of lines for the
assignments, and in functional language you pile them up as arguments
to the left in the tail call, effectively emulating states. It's like
writing a program horizontally. :)

Hung Jung
Jul 18 '05 #12
>> # Setup: transitionScore['AF'] = soundScoreMatrix[0][5].
transitionScore = {}
for i in range(26):
first = chr(65+i)
row = soundScoreMatrix[i]
for j in range(26):
transitionScore[first + chr(65+j)] = row[j]

That would create another list containing all possible transitions,
right? Are you doing this just to avoid indexing the matrix later when
going over the phrase letter by letter?


He's creating a dictionary. And yes, he's using it to avoid indexing
into the matrix. When you are dealing with some sort of object that is
indexed by pairs (or triples or quads) of objects, it is quite Pythonic
to index that object by those same blocks.
import this

The Zen of Python, by Tim Peters
Jul 18 '05 #13

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

Similar topics

0
by: Hans Maurer | last post by:
>Description: We're running our current TTS application with MySQL (on Unix). All database, table and column names are in lower-case. However, we need to access this database with a new...
7
by: codeslayer | last post by:
Greetings to everyone in ‘forum-land': I have a problem that has plaguing me to no end. It is a CSS-related question, and I have not seen this question posted anywhere in forums or through...
5
by: caviar | last post by:
Hi, i'm having a problem with a native w32 dll. Everything is working fine except for one parameter which is defined as: --------------------------------------header file--- // short PASFIX...
2
by: Don | last post by:
I'm having problems with intellisense, autocomplete, etc. suddenly not working in certain classes of a project I'm working on. All the options are set, and it all works fine for most classes, but...
6
by: Nx | last post by:
i've got it all working nicely in firefox, but whenever i test it in IE none of the onclick events are triggered. i'm using an xsl to transform an rss feed into a photogallery. when i try to...
4
by: Jim Langston | last post by:
Expected output is: Three One One Actual output is: Three One Two
3
by: ljungers | last post by:
Have a couple of conditions going on that I can't seem to get working correctly. Have 1 Form only with 3 text boxes that are used in a query, when a command button is clicked using 'Event...
8
by: shyamg | last post by:
plzzz help me............
5
by: =?Utf-8?B?UVNJRGV2ZWxvcGVy?= | last post by:
I am trying to get the DNS name of an arbitrary IP address on the network. If I use GetHostEntry as the documentation suggests I only get the name of the machine I am running the code on. All...
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: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
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
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
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...
0
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,...
0
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...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

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.