Slicing a string in Python - python

When we need to slice a string at a particular location, we need to know the index from where we want to.
For example, in the string:
>>> s = 'Your ID number is: 41233'
I want to slice the string starting from : and get the number.
Sure I can count at what index : is and then slice, but is that really a good approach?
Of course I can do a s.index(':'). But that would be an extra step, so I came up with something like:
>>> print s[(s.index(':')+2):]
41233
But somehow I don't like the looks of it.
So my question is, given a long string which you want to slice, how do you find the index from where to begin the slicing in the easiest and most readable way? If there is a trick to do it orally, I would love to know that.

Perhaps you could use split():
>>> s = 'Your ID number is: 41233'
>>> print s.split(":")[1].strip()
41233

text, sep, number = 'Your ID number is: 41233'.partition(':')
print number
works too. But it won't fail if the separator is not in the string.
That unpacking works for split too:
text, number = 'Your ID number is: 41233'.split(':',1)

Another approach is 'Your ID number is: 41233'.split(':')[1].strip().

So my question is, given a long string which you want to slice, how do you find the index from where to begin the slicing in the easiest and most readable way?
When "where to begin the slicing" is a specific symbol, you don't; instead you just as Python to split the string up with that symbol as a delimiter, or partition it into the bits before/within/after the symbol, as in the other answers. (split can split the string into several pieces if several delimiters are found; partition will always give three pieces even if the symbol is not there at all.)
If there is a trick to do it orally, I would love to know that.
I really don't think you mean "orally". :)

I wouldn't use slicing at all unless there's some other compelling reason you want to do so. Instead, this sounds like a perfect job for re the regular expression module in the standard library. Here's an example of using it to solve your problem:
import re
compile_obj = re.compile(r'Your ID number is:\s(?P<ID>\d+)')
s = 'Your ID number is: 41233'
match_obj = compile_obj.search(s)
if match_obj:
print match_obj.group('ID')
# 41233

Recently came across partition
string = "Your ID number is: 41233"
string = string.partition(':')
print string[2]

Related

How to round numbers in place in a string in python

I'd like to take some numbers that are in a string in python, round them to 2 decimal spots in place and return them. So for example if there is:
"The values in this string are 245.783634 and the other value is: 25.21694"
I'd like to have the string read:
"The values in this string are 245.78 and the other value is: 25.22"
What you'd have to do is find the numbers, round them, then replace them. You can use regular expressions to find them, and if we use re.sub(), it can take a function as its "replacement" argument, which can do the rounding:
import re
s = "The values in this string are 245.783634 and the other value is: 25.21694"
n = 2
result = re.sub(r'\d+\.\d+', lambda m: format(float(m.group(0)), f'.{n}f'), s)
Output:
The values in this string are 245.78 and the other value is: 25.22
Here I'm using the most basic regex and rounding code I could think of. You can vary it to fit your needs, for example check if the numbers have a sign (regex: [-+]?) and/or use something like the decimal module for handling large numbers better.
Another alternative using regex for what it is worth:
import re
def rounder(string, decimal_points):
fmt = f".{decimal_points}f"
return re.sub(r'\d+\.\d+', lambda x: f"{float(x.group()):{fmt}}", string)
text = "The values in this string are 245.783634 and the other value is: 25.21694"
print(rounder(text, 2))
Output:
The values in this string are 245.78 and the other value is: 25.22
I'm not sure quite what you are trying to do. "Round them in place and return them" -- do you need the values saved as variables that you will use later? If so, you might look into using a regular expression (as noted above) to extract the numbers from your string and assign them to variables.
But if you just want to be able to format numbers on-the-fly, have you looked at f-strings? f-string
print(f"The values in this string are {245.783634:.2f} and the other value is: {25.21694:.2f}.")
output:
The values in this string are 245.78 and the other value is: 25.22.
You can use format strings simply
link=f'{23.02313:.2f}'
print(link)
This is one hacky way but many other solutions do exist. I did that in one of my recent projects.

Error when trying to create a variable that stores a range of characters: TypeError : indices must be integers or None or have an __index__ method

I'm new to programming and have been tasked to prompt the user to enter a string, and from there generate a random number that will be a valid index of the user's string, and whatever the generated index is till the end of the string I have to replace the characters within that range with "*".
e.g. (desired output)
Please enter a string: hello
assume random index is 2
The new string is: he***
What I was thinking of doing is firstly creating a variable that stores the range of characters that I am trying to replace, like so:
user_string = "sentence xyz"
length_of_string = len(user_string)
index_start = random.randint(1,length_of_string)
chars_to_replace = user_string[index_start:]
This worked well and printing out the chars_to_replace variable to test worked as expected.
I then wanted to create another variable that stores the rest of the characters that were to remain, like so:
chars_to_keep = user_string[:chars_to_replace]
This line of code resulted in this error message:
TypeError: slice indices must be integers or None or have an __index__ method
What I was ultimately trying to do was to replace all the characters in the chars_to_replace variable with * and concatenate it with the other chars_to_keep variable and as a result produce a similar result to the desired output above.
If anyone could point me in the right direction as to what I'm doing wrong that would be greatly appreciated, additionally our teacher wanted us to showcase our understanding of what she has taught us, (really basic string manipulation) so solutions that employ complex line(s) of code is probably out of scope for this simple task. I know y'all probably find it absurd that I'm essentially asking for a super inefficient way of solving this task when there's a simple way of doing it but this will help me understand the basics better and build a good foundation to work with, thanks!
The error is due to chars_to_replace is not an integer. For slicing, it should be an integer. To achieve your goal it can be achieve like this
user_string = "sentence xyz"
length_of_string = len(user_string)
index_start = random.randint(1,length_of_string)
chars_to_keep = user_string[:index_start] + '*' * (length_of_string - index_start + 1)
print(chars_to_keep)
The problem in:
chars_to_keep = user_string[:chars_to_replace]
is that you are trying to slice using a string instead of an Integer.
chars_to_replace is a string and not an Integer.
Correct code would be:
chars_to_keep = user_string[:index_start]
Also your overall code could look like this for the expected output:
user_string = "sentence xyz"
length_of_string = len(user_string)
index_start = random.randint(1,length_of_string)
result = user_string[:index_start] + '*' * (length_of_string - index_start)

Get multiple strings from array indices - PYTHON

I just can not figure it out how to easily do it in python:
myArray = ["this ","is ","a ","test.","this ","is ","another ","test."]
now I want the output to be
print(myArray[0:3]) -> "this is a test"
print(myArray[4:7]) -> "this is another test"
Is there a feature in python that allows this without iterating over the whole array within a for word in myArray ...
What I get is an index in a loop which only tells me up to which word I should "print" it.
I prefer a python "exclusive" variant, which is short and simple, best case a one liner and it should need as less memory as possible (fast even for thousands of attempts)
You can try join(), I hope this is the solution you are looking for
myArray = ["this ","is ","a ","test.","this ","is ","another ","test."]
print(' '.join(myArray[:4]))
print(' '.join(myArray[4:]))
It seems like what you actually want is to join together some sublist in your list of words.
>>> myArray = ["this ","is ","a ","test.","this ","is ","another ","test."]
>>> print(''.join(myArray[0:4]))
this is a test.
>>> print(''.join(myArray[4:8]))
this is another test.
I guess you have to make it myArray[0:4] and join function...
print("".join(myArray[0:4]))
print("".join(myArray[4:8]))
You need to use the string method join(). This method applies to a separator. For instance:
"".join(myArray[0:4])
Will output:
'this is a test.'
You were close.
For python 2.7:
print " ".join(test[0:3])
For python 3.x:
print(*test[0:3])
As the other guys have said, you can always use join:
//generate 10 letters
myArray = [chr(letter) for letter in range(97,107)]
//return letters from 0 to 5
"".join(myArray)[0:5]
However, I don't understand why you can't use this format
print[0:5]
In terms of efficiency, the latter option is better, and it is just as pythonic as the former.
When you 'join' the array, you are implicitly interating over it, and when you finally display the necessary elements, you are iterating again.
just use the join()
first="".join(myArray[0:3])
second="".join(myArray[4:7])
as friends have told you can use join in python:
print("".join(myArray[x:y]))
which puts what you call join on it (here "") between elements as seperator and returns as string.
one good way is just remove ending space from your array and do like this:
print(" ".join(myArray[x:y]))
print(''.join(myArray[:4])) -> "this is a test"
print(''.join(myArray[4:])) -> "this is another test"

How to hide part of string in python

I am just wondering if there is such possibility to hide somehow part of string in python. I am not talking about slicing. I am talking about situation where I have "1somestring," while printing I obtain "somestring". 1 before somestring should be visible for python but not displayable. Or It could be nice to have some kind of indicator glued to string. What I want to achieve is custom sorting. I have list of strings and I want to sort them by addition of digits in front of them. Sorting will proceed basing on digits thus behind digits I can insert whatever I want, but I don’t want to have digits visible. Thanks for answers in advance.
You could store them in a list, with each entry consisting of a tuple indicating order (low to high), then the string. The default sorting on this list would place them in order.
words = [(1,"blah"), (3,"wibble"), (2,"splop")]
words.sort()
print(words)
[(1, 'blah'), (2, 'splop'), (3, 'wibble')]
print(" ".join(word[1] for word in words))
blah splop wibble
I think something simple like a situation where you have a list of things like:
['1something', '2more', '3another']
is to modify each element using an empty substitution, then print:
import re
for item in list:
charonly = re.sub('[0-9]','', item)
print charonly
This does not require "hiding" information in your string. It simply requires combining them with your other information (the numbers) at sorting time, and that can be done in many ways. Here's one:
# my strings, and the order I'd like them to have
my_strings = ["how", "there", "hello", "you", "are"]
my_ordering = [2, 1, 0, 3, 4]
# sort them
sorted_strings = [x for _, x in sorted(zip(my_ordering, my_strings))]
print(sorted_strings)
You can define a print function other than the built-in one. So this might not be exactly seek, what you want to do is better explained in the comments. But this is also a way.
def print2(string):
print "".join(letter for letter in string if letter.isalpha())
In you script, if you restrict the usage of the print function and only use the one you defined. It could be a solution.
I will ask to the question in the title:
Let's say that our string is:
ceva="123Password"
If you want to hider first 2:
ceva=ceva[2:]
ceva will be '3Password'
Now let's play with list of strings:
lista=["abc","ghi","def"]
for _,x in enumerate(sorted(lista)):
print(str(_)+x)
0abc
1def
2ghi
or
lista=["abc","ghi","def"]
for _,x in enumerate(sorted(lista)):
lista[_]=str(_)+x
>>> lista
['0abc', '1def', '2ghi']

What's the most Pythonic way to remove a number from start of a string?

I have various strings
123_dog
2_fish
56_cat
45_cat_fish
There is always one number. Always a '_' after the number.
I need to remove the number and the underscore. I can use regex, but I wonder if there is some pythonic way that uses builtin methods?
(I'm an experienced coder - but new to Python.)
Assuming that there is always an underscore after the number, and that there is always exactly a single number, you can do this:
s = '45_cat_fish'
print s.split('_', 1)[1]
# >>> cat_fish
The argument to split specifies the maximum number of splits to perform.
Using split and join:
>>> a="45_cat_fish"
>>> '_'.join(a.split('_')[1:])
'cat_fish'
Edit: split can take a maxsplit argument (see YS-L answer), so '_'.join is unnecessary, a.split('_',1)[1]…
Using find
>>> a[a.find('_')+1:]
'cat_fish'
Another way is:
s = "45_cat_fish"
print ''.join(c for c in s if c.isalpha() or c == '_')[1:]
gives cat_fish

Categories