Print the first chars of a list (beginner) - python

so far this is my code
def firstChars( s ):
for word in s:
print (s[0][0])
this is what it prints:
>>> s='hello','world'
>>> firstChars(s)
h
h
how do i alter this code so that it prints out 'h' and 'w'?

s[0] will always be the first element in the sequence passed to the function. In order to use the specific word being examined in the for loop just above, use word within the loop instead.

word represents each element of the tuple/iterable. For the tuple ("Hello", "World"), word will be equal to "Hello" then "World". To get the first letter of each, subscript the word: word[0].
Note that this isn't the safest approach, as it will crash on an empty string (because "" doesn't have a 0-th element). I might define a "firstLetter" function that deals with the cases of an empty string if you can't guarantee that the string won't be empty.
To elaborate on JL's answer, what you wrote runs "fine" because Strings and tuples are both iterable (like a list).
When you wrote s[0][0], s[0] evaluated to "Hello", then you're left with "Hello"[0], which evaluates to 'H'. It output twice, once for each loop iteration because you based the loop on the tuple, which had 2 elements.

Alternative pythonic way
s='hello','world'
print('\r\n'.join(item[0] for item in s))
h
w

with the for word in s loop, word will first point to the first element of s, then to the second etc. If the explanation doesn't make sense to you, just run this:
def each_word(s):
for word in s:
print s
s = ("hello", "wolrd")
each_word(s)
Now the first char of a string word is word[0], and this should be enough to solve your problem.

for word in s:
print (s[0][0])
in this code fragment word becomes each element of s in turn -- s[0] ('hello') then s[1] ('world'). Whereas s[0][0] directly accesses the first element of the first element of s ('h'). you are looking to access the first element of each element in turn. So:
for word in s:
print (word[0])
will do what you are trying to accomplish.

This works. Now, one bit of warning, and it goes back to another comment about naming. In Python, it can be very hard to distinguish a string from a list or a tuple. They all iterate, they all have lengths and indices.
Be careful in how you name things, because there is no compiler to catch goofups.
def firstChars( s ):
#iterate through list/tuple passed in
for word in s:
#now, pick the first character
print (word[0])

Try this:
def firstChars( s ):
for word in s:
print (word[0])
In the function firstChars, you correctly loop over the items in s, but note that inside the for block, you should use word as that is the variable that is assigned the current item in s.
Also note that when you have multiple indices lined up as ins[0][0], each one "digs deeper" into the previous item. So, s[0] refers to the first item in s (the string 'hello'), the following [0] refers to the first char of that item ('h').

Related

Why the output is two string when I pass a one character string to a python function

I've created a function called swap for an experiment. The function is as below:
def swap(x):
return x[-1:] + x[1:-1] + x[0:1]
When I try to pass a string "a", the output is "aa". I am not sure how's that happen. Thanks in advance if someone knows the reason.
Your function returns a new string based on:
The last letter of your string (a)
everything after the first letter but before the last letter (empty in your case)
and the first letter of your string (a)
So because your last letter is your first letter, you get them twice.
To swap them correctly, you'll have to test for string length:
def swap(x):
if len(x) < 2:
return x
return x[-1] + x[1:-1] + x[0]
Now that you know that in the last line x is at least two characters long, you also don't need slicing for the first/last character and can use direct element access (x[0]/x[-1]).
Actually this is ok.
x[-1:] will return the last character, becuase -1 starts from the end
x[0:1] will return the first character from beginning
x[1:-1] is nothing in this case because you don't have the second character
Btw for swap use return x.reverse() or return x[::-1]

How would I put back together a string after iterating it?

As the title says, I am confused on how to put back the string into a line after iterating through it.
Right now I have this:
for element in want_cyphered:
element = ord(element)
element = element + 13
element = chr(element)
print(element)
This iterates through the want_cyphered string and prints it. This is a function I'm using for a cipher and decipherer. What I was wondering is how to compile the iteration into an actual line again? Right now, my print is one character per line, but I want it to be all on one line. Any help would be appreciated! Using python.
The other answers aren't wrong, but since you're using Python, you may as well use what it's good at (and your code is likely to be faster as well):
want_cyphered = 'Some text'
cyphered = ''.join(chr(ord(ch) + 13) for ch in want_cyphered)
print(cyphered)
decyphered = ''.join(chr(ord(ch) - 13) for ch in cyphered)
print(decyphered )
To break that down (assuming you're new at Python): ''.join(list_of_parts) takes a list of string parts (characters or strings) and joins them together into a single string, using whatever the string at the start is - an empty string in this case.
You can generate that list of parts using a generator expression (a very well performing way of iterating over something iterable) like [ch for ch in some_str], which would get you a list of characters in a string.
I've put the generator in square brackets just now so that it would become an actual list, but when you only write a generator to use as the input to some function, you can just pass the generator itself, without the brackets like ''.join(ch for ch in some_str) - which basically does nothing. It takes the string apart and puts it back together again.
But you can apply operations to the elements of that generator as well, so instead of just ch, you could fill the list with chr(ord(ch) + 13) which is the cypher you were looking to apply.
Put all that together and you get:
cyphered = ''.join(chr(ord(ch) + 13) for ch in want_cyphered)
Create a variable and append your element to the variable inside the loop. When the loop ends print the result.
result = ""
for element in want_cyphered:
element = ord(element)
element = element + 13
element = chr(element)
result += element
print(result)
Or if you want to get really fancy...
print("".join([chr(ord(e) + 13) for e in want_cyphered]))
just do
for element in want_cyphered:
element = ord(element)
element = element + 13
element = chr(element)
print(element,end="")
the end="" part tells Python to add a empty string at the end. The end paramter defaults to a new line so it prints each character on one line. Setting end="" makes it all print on one line.
Just make an empty string and on each iteration, add the element to it!
want_cyphered = "Hello, World!"
cyphered = ""
for element in want_cyphered:
element = ord(element)
element = element + 13
element = chr(element)
# Add the element to string
cyphered += element
Here is an approach that uses the translate, make_trans functions.
from string import ascii_lowercase as lc, ascii_uppercase as uc
def rot_13(s):
return s.translate(str.maketrans(lc+uc, lc[13:]+lc[:13]+uc[13:]+uc[:13]))
s = 'Hello World!'
print(rot_13(s))
Prints
Uryyb Jbeyq!

Problem with a complicated program that finds the longest substring in which chars are in alphabetical order

I found this solution which seems to work :
def longest_ascending(s):
matches = []
current = [s[0]]
for index, character in enumerate(s[1:]):
if character >= s[index]:
current.append(character)
else:
matches.append(current)
current = [character]
matches.append(current)
return "".join(max(matches, key=len))
print(longest_ascending(s))
Aren't character and indexed s always the same characters ?
For example if 'ababc' was stored in the s variable, the first ''for'' iteration would go over ''if 'b'>=s[1]'', which basically is ''if 'b'>='b''', the second one would contain the statement ''if 'a'>='a''' and so on, which means the ''else'' block would never actually get executed.
So, how exactly does the program function the way it does ?
Notice that you are enumerating s[1:], but indexing s. If s is 'abc', then the first pair out of the enumeration is (0, 'b'), and s[0] is 'a'.

For loop for finding index in string

I'm wondering why my function does not call the index of the character in the string. I used a for loop for this, and for some reason it's just listing all of the possible indices of the string. I made a specific if statement, but I don't get why it's not following the instructions.
def where_is(char,string):
c=0
for char in string:
if char==(string[c]):
print (c)
c+=1
else:
print ("")
where_is('p','apple')
Your loop is overwriting your parameter char. As soon as you enter your loop, it is overwritten with a character from the string, which you then compare to itself. Rename either your parameter or your loop variable. Also, your counter increment c+=1 should also be outside of your if. You want to increase the index whether or not you find a match, otherwise your results are going to be off.
And just as a matter of style, you don't really need that else block, the print call will just give you extra newlines you probably don't want.
Firstly, the index you used is not being increased in the else part and secondly, I generally prefer a while loop to a for loop when it comes to iterating through strings. Making slight modifications to your code, have a look at this :
def where_is(char,string):
i=0
while i<len(string):
if char==(string[i]):
print (i)
else:
print ("")
i+=1
where_is('p','apple')
Input : where_is('p','apple')
Output: 1 2
Check it out here
The problem is that the given code iterated over everything stored in the string and as it matched everytime the value of 'c' increased and got printed.
I think your code should be:
def where_is(char, string):
for i in range(len(string)):
if char == (string[i]):
print(i)
where_is('p', 'apple')
This prints the index of all the 'p's in 'apple'.
As mentioned in the comments, you don't increment correctly in your for loop. You want to loop through the word, incrementing each time and outputting the index when the letter is found:
def where_is(char, word):
current_index = 0
while current_index < len(word):
if char == word[current_index]:
print (current_index)
current_index += 1
where_is('p', 'apple')
Returning:
1
2
Alternatively, by using enumerate and a list comprehension, you could reduce the whole thing down to:
def where_is(char, word):
print [index for index, letter in enumerate(word) if letter == char]
where_is('p', 'apple')
which will print:
[1,2]
You then also have the option of return-ing the list you create, for further processing.

python and palindromes

i recently wrote a method to cycle through /usr/share/dict/words and return a list of palindromes using my ispalindrome(x) method
here's some of the code...what's wrong with it? it just stalls for 10 minutes and then returns a list of all the words in the file
def reverse(a):
return a[::-1]
def ispalindrome(a):
b = reverse(a)
if b.lower() == a.lower():
return True
else:
return False
wl = open('/usr/share/dict/words', 'r')
wordlist = wl.readlines()
wl.close()
for x in wordlist:
if not ispalindrome(x):
wordlist.remove(x)
print wordlist
wordlist = wl.readlines()
When you do this, there is a new line character at the end, so your list is like:
['eye\n','bye\n', 'cyc\n']
the elements of which are obviously not a palindrome.
You need this:
['eye','bye', 'cyc']
So strip the newline character and it should be fine.
To do this in one line:
wordlist = [line.strip() for line in open('/usr/share/dict/words')]
EDIT: Iterating over a list and modifying it is causing problems. Use a list comprehension,as pointed out by Matthew.
Others have already pointed out better solutions. I want to show you why the list is not empty after running your code. Since your ispalindrome() function will never return True because of the "newlines problem" mentioned in the other answers, your code will call wordlist.remove(x) for every single item. So why is the list not empty at the end?
Because you're modifying the list as you're iterating over it. Consider the following:
>>> l = [1,2,3,4,5,6]
>>> for i in l:
... l.remove(i)
...
>>> l
[2, 4, 6]
When you remove the 1, the rest of the elements travels one step upwards, so now l[0] is 2. The iteration counter has advanced, though, and will look at l[1] in the next iteration and therefore remove 3 and so on.
So your code removes half of the entries. Moral: Never modify a list while you're iterating over it (unless you know exactly what you're doing :)).
I think there are two problems.
Firstly, what is the point in reading all of the words into a list? Why not process each word in turn and print it if it's a palindrome.
Secondly, watch out for whitespace. You have newlines at the end of each of your words!
Since you're not identifying any palindromes (due to the whitespace), you're going to attempt to remove every item from the list. While you're iterating over it!
This solution runs in well under a second and identifies lots of palindromes:
for word in open('/usr/share/dict/words', 'r'):
word = word.strip()
if ispalindrome(word):
print word
Edit:
Perhaps more 'pythonic' is to use generator expressions:
def ispalindrome(a):
return a[::-1].lower() == a.lower()
words = (word.strip() for word in open('/usr/share/dict/words', 'r'))
palindromes = (word for word in words if ispalindrome(word))
print '\n'.join(palindromes)
It doesn't return all the words. It returns half. This is because you're modifying the list while iterating over it, which is a mistake. A simpler, and more effective solution, is to use a list comprehension. You can modify sukhbir's to do the whole thing:
[word for word in (word.strip() for word in wl.readlines()) if ispalindrome(word)]
You can also break this up:
stripped = (word.strip() for word in wl.readlines())
wordlist = [word for word in stripped if ispalindrome(word)]
You're including the newline at the end of each word in /usr/share/dict/words. That means you never find any palindromes. You'll speed things up if you just log the palindromes as you find them, instead of deleting non-palindromes from the list, too.

Categories

Resources