loop iterations ignore spaces?

This is the place for queries that don't fit in any of the other categories.

loop iterations ignore spaces?

Postby Hypernova » Sat Jun 29, 2013 6:31 pm

Here's another problem for you helpful fellows;

My code takes a string that's been simply encrypted using an alphabetic character shift method, decodes it, and outputs the line in it's original form. So if the shift was -2, "d" would be "b" etc. Problem is when I use a forloop, it skips any spaces in a string. I need to output the code with the spaces, and splitting the string to keep the words separate seems like a really complicated way of doing it. Any hints? Thanks plenty in advance :)

here's my inadequate code with a forloop, at the moment;

Code: Select all
code= input()
s=1
def decode(code,s):
   a=""
   for i in range (len(code)):
      a+= chr(ord(code[i])-s)
   return a
print(decode(code,s))
Hypernova
 
Posts: 18
Joined: Mon Jun 10, 2013 12:23 am

Re: loop iterations ignore spaces?

Postby micseydel » Sat Jun 29, 2013 6:41 pm

If I were you, I'd switch to a regular for loop instead of one over the indexes
Code: Select all
for char in code:
    if char == ' ':
        continue
    #if we haven't continued, we can shift after this


Also, it's probably a good idea to create a list and then use str.join() on it rather than string concatenation in the for loop. Also, you code could shift letters into non-letter ASCII characters. Is this intentional? If not, you might want to look into str.translate() and string.maketrans().
Join the #python-forum IRC channel on irc.freenode.net!
User avatar
micseydel
 
Posts: 1129
Joined: Tue Feb 12, 2013 2:18 am
Location: Mountain View, CA

Re: loop iterations ignore spaces?

Postby Hypernova » Sat Jun 29, 2013 8:42 pm

micseydel wrote:If I were you, I'd switch to a regular for loop instead of one over the indexes
Code: Select all
for char in code:
    if char == ' ':
        continue
    #if we haven't continued, we can shift after this


Also, it's probably a good idea to create a list and then use str.join() on it rather than string concatenation in the for loop. Also, you code could shift letters into non-letter ASCII characters. Is this intentional? If not, you might want to look into str.translate() and string.maketrans().


I was actually using that type of loop initially, but I changed it to the index loop to see if that would stop it from skipping spaces, which it didn't, so I'll change it back as you suggest. Shifting to non-ASCII letters wasn't intentional, it's just something I hadn't got to addressing yet because the space skipping seems like it should be my first priority. I'll look into those methods too, but I want to code with my basic knowledge first before increasing my language "vocabulary" further just so there's more problems and things on which to practice on in the meantime.

I just fiddled about with it some more, and it seems my loop was ignoring spaces because whatever chr(ord(" ")-1) is, it returns as a stripping of the space. When I wrote chr(ord(" ")+1), it returned "!", so at least I understand what was going on there (and the length of the string remains the same).

So with the if condition, I can add that space to the string either by writing a str.join() or by concatenation before the continue statement, right?

Thanks tonnes for your input micseydel.
Hypernova
 
Posts: 18
Joined: Mon Jun 10, 2013 12:23 am

Re: loop iterations ignore spaces?

Postby ochichinyezaboombwa » Sun Jun 30, 2013 7:48 pm

Your loop was not ignoring spaces or anything: how could it without the if?!? (or without filter() or list comprehension, but that's a longer story).

It looked to you as spaces are skipped simply because chr(ord(" ")-1) is an invisible character (it is there for historical reasons mostly; search for "ascii table").

1) The usual idiom for filtering is something like this:
Code: Select all
for ch in smth:
    if cond1(ch): # add the ch itself to the result
    else: # add some_formula(ch) to the result

2) You can use string concatenation (as you do):
Code: Select all
def toupper1(s):
    r = ""
    for ch in s:
        r += ch.upper()
    return r

But it's considered a better technique to use list to obtain the same result:
Code: Select all
def toupper2(s):
    r = [] # list !
    for ch in s:
        r.append(ch.upper())
    return "".join(r) # join


This is (or at least should be) better for performance reasons.

3) what happens if the shift == 500? or -500?
What you probably (I am guessing but i bet I'm right that you are implementing a Caesar's cipher) need is:
a -> c, b -> d, ... , x -> z, y -> a, b -> c
right? Well your code doesn't do that.

Don't hesitate to ask more questions, but better don't rely just on us.
ochichinyezaboombwa
 
Posts: 200
Joined: Tue Jun 04, 2013 7:53 pm


Return to General Coding Help

Who is online

Users browsing this forum: No registered users and 3 guests