Reputation: 10162
Python programs are often short and concise and what usually requires bunch of lines in other programming languages (that I know of) can be accomplished in a line or two in python. One such program I am trying to write was to extract every other letters from a string. I have this working code, but wondering if any other concise way is possible?
>>> s
'abcdefg'
>>> b = ""
>>> for i in range(len(s)):
... if (i%2)==0:
... b+=s[i]
...
>>> b
'aceg'
>>>
Upvotes: 10
Views: 76323
Reputation: 6120
Here is another example both for list and string:
sentence = "The quick brown fox jumped over the lazy dog."
sentence[::2]
Here we are saying: Take the entire string from the beginning to the end and return every 2nd character.
Would return the following:
'Teqikbonfxjme vrtelz o.'
You can do the same for a list:
colors = ["red", "organge", "yellow","green", "blue"]
colors[1:4]
would retrun:
['organge', 'yellow', 'green']
The way I read the slice is: If we have sentence[1:4]
Start at index 1 (remember the starting position is index 0) and Stop BEFORE the index 4
Upvotes: 2
Reputation: 365945
The right way to do this is to just slice the string, as in the other answers.
But if you want a more concise way to write your code, which will work for similar problems that aren't as simple as slicing, there are two tricks: comprehensions, and the enumerate
function.
First, this loop:
for i in range(len(foo)):
value = foo[i]
something with value and i
… can be written as:
for i, value in enumerate(foo):
something with value and i
So, in your case:
for i, c in enumerate(s):
if (i%2)==0:
b+=c
Next, any loop that starts with an empty object, goes through an iterable (string, list, iterator, etc.), and puts values into a new iterable, possibly running the values through an if
filter or an expression that transforms them, can be turned into a comprehension very easily.
While Python has comprehensions for lists, sets, dicts, and iterators, it doesn't have comprehensions for strings—but str.join
solves that.
So, putting it together:
b = "".join(c for i, c in enumerate(s) if i%2 == 0)
Not nearly as concise or readable as b = s[::2]
… but a lot better than what you started with—and the same idea works when you want to do more complicated things, like if i%2 and i%3
(which doesn't map to any obvious slice), or doubling each letter with c*2
(which could be done by zipping together two slices, but that's not immediately obvious), etc.
Upvotes: 2
Reputation: 11060
Practically, slicing is the best way to go. However, there are also ways you could improve your existing code, not by making it shorter, but by making it more Pythonic:
>>> s
'abcdefg'
>>> b = []
>>> for index, value in enumerate(s):
if index % 2 == 0:
b.append(value)
>>> b = "".join(b)
or even better:
>>> b = "".join(value for index, value in enumerate(s) if index % 2 == 0)
This can be easily extended to more complicated conditions:
>>> b = "".join(value for index, value in enumerate(s) if index % 2 == index % 3 == 0)
Upvotes: 0
Reputation: 31262
you could try using slice and join:
>>> k = list(s)
>>> "".join(k[::2])
'aceg'
Upvotes: 0
Reputation:
Use Explain Python's slice notation:
>>> 'abcdefg'[::2]
'aceg'
>>>
The format for slice notation is [start:stop:step]
. So, [::2]
is telling Python to step through the string by 2's (which will return every other character).
Upvotes: 18