Delphi has functions
Insert (insert substring Str2 into string Str at offset P) and
Delete (delete N chars from string Str at offset P).
What is analog of them in Python for strings?
You can use
s1[:p] + s2 + s1[p:]
s1[:p] + s1[p+n:]
For example:
>>> s1 = 'hello world'
>>> s2 = 'xyz'
>>> p = 3
>>> s1[:p] + s2 + s1[p:]
'helxyzlo world'
>>> n = 2
>>> s1[:p] + s1[p+n:]
'hel world'
Python strings are immutable, so you can't modify an existing string -- but you can apply those operations to a string and produce a new one.
Probably the best way to do it is slicing, an extension of the indexing syntax to allow you to pull out multiple characters. So:
>>> 'abcde'[1:4]
'bcd'
Notice that the first index is inclusive, but the second index is exclusive. That's weird at first, but it's a ubiquitous convention in Python.
If you leave out the first or last index, the slice goes to the beginning or end of the string, respectively:
>>> 'abcde'[1:]
'bcde'
>>> 'abcde'[:4]
'abcd'
Finally, you can use the + operator for string concatenation:
>>> 'abc' + 'de'
'abcde'
With all these parts together, you can insert and delete substrings as you like:
>>> s = 'abcde'
>>> s[:2] + 'XYZ' + s[2:] # Insert 'XYZ' before index 2
'abXYZcde'
>>> s[:2] + s[4:] # Delete indices from 2 to before 4
'abe'
If you wanted insert and delete functions as you've described them, you'd be writing them yourself -- but that wouldn't be hard. Spoiler alert -- you may want to give it a try yourself before reading the code below. :)
def insert(str, str2, p):
return str[:p] + str2 + str[p:]
def delete(str, p, n):
return str[:p] + str[p + n:]
(You could probably come up with better argument names -- in particular, using str is inadvisable because it's also the name of a Python builtin -- but for this example I've intentionally used the same ones you used in the question.)
Related
I'm trying to make a function, f(x), that would add a "-" between each letter:
For example:
f("James")
should output as:
J-a-m-e-s-
I would love it if you could use simple python functions as I am new to programming. Thanks in advance. Also, please use the "for" function because it is what I'm trying to learn.
Edit:
yes, I do want the "-" after the "s".
Can I try like this:
>>> def f(n):
... return '-'.join(n)
...
>>> f('james')
'j-a-m-e-s'
>>>
Not really sure if you require the last 'hyphen'.
Edit:
Even if you want suffixed '-', then can do like
def f(n):
return '-'.join(n) + '-'
As being learner, it is important to understand for your that "better to concat more than two strings in python" would be using str.join(iterable), whereas + operator is fine to append one string with another.
Please read following posts to explore further:
Any reason not to use + to concatenate two strings?
which is better to concat string in python?
How slow is Python's string concatenation vs. str.join?
Also, please use the "for" function because it is what I'm trying to learn
>>> def f(s):
m = s[0]
for i in s[1:]:
m += '-' + i
return m
>>> f("James")
'J-a-m-e-s'
m = s[0] character at the index 0 is assigned to the variable m
for i in s[1:]: iterate from the second character and
m += '-' + i append - + char to the variable m
Finally return the value of variable m
If you want - at the last then you could do like this.
>>> def f(s):
m = ""
for i in s:
m += i + '-'
return m
>>> f("James")
'J-a-m-e-s-'
text_list = [c+"-" for c in text]
text_strung = "".join(text_list)
As a function, takes a string as input.
def dashify(input):
output = ""
for ch in input:
output = output + ch + "-"
return output
Given you asked for a solution that uses for and a final -, simply iterate over the message and add the character and '-' to an intermediate list, then join it up. This avoids the use of string concatenations:
>>> def f(message)
l = []
for c in message:
l.append(c)
l.append('-')
return "".join(l)
>>> print(f('James'))
J-a-m-e-s-
I'm sorry, but I just have to take Alexander Ravikovich's answer a step further:
f = lambda text: "".join([c+"-" for c in text])
print(f('James')) # J-a-m-e-s-
It is never too early to learn about list comprehension.
"".join(a_list) is self-explanatory: glueing elements of a list together with a string (empty string in this example).
lambda... well that's just a way to define a function in a line. Think
square = lambda x: x**2
square(2) # returns 4
square(3) # returns 9
Python is fun, it's not {enter-a-boring-programming-language-here}.
Is it possible without regex in python to print the first n integers from a string containing both integers and characters?
For instance:
string1 = 'test120202test34234e23424'
string2 = 'ex120202test34234e23424'
foo(string1,6) => 120202
foo(string2,6) => 120202
Anything's possible without a regex. Most things are preferable without a regex.
On easy way is.
>>> str = 'test120202test34234e23424'
>>> str2 = 'ex120202test34234e23424'
>>> ''.join(c for c in str if c.isdigit())[:6]
'120202'
>>> ''.join(c for c in str2 if c.isdigit())[:6]
'120202'
You might want to handle your corner cases some specific way -- it all depends on what you know your code should do.
>>> str3 = "hello 4 world"
>>> ''.join(c for c in str3 if c.isdigit())[:6]
'4'
And don't name your strings str!
You can remove all the alphabets from you string with str.translate and the slice till the number of digits you want, like this
import string
def foo(input_string, num):
return input_string.translate(None, string.letters)[:num]
print foo('test120202test34234e23424', 6) # 120202
print foo('ex120202test34234e23424', 6) # 120202
Note: This simple technique works only in Python 2.x
But the most efficient way is to go with the itertools.islice
from itertools import islice
def foo(input_string, num):
return "".join(islice((char for char in input_string if char.isdigit()),num))
This is is the most efficient way because, it doesn't have to process the entire string before returning the result.
If you didn't want to process the whole string - not a problem with the length of strings you give as an example - you could try:
import itertools
"".join(itertools.islice((c for c in str2 if c.isdigit()),0,5))
I have a list :list = [1,2,3]. And I would like to convert that into a string with parentheses: string = (1,2,3).
Currently I am using string replace string = str(list).replace('[','(').replace(']',')'). But I think there is a better way using regex.sub. But I have no idea how to do it. Thanks a lot
If you do indeed have a list, then:
>>> s = [1,2,3]
>>> str(tuple(s))
'(1, 2, 3)'
You could use string.maketrans instead -- I'm betting it runs faster than a sequence of str.replace and it scales better to more single character replacements.
>>> import string
>>> table = string.maketrans('[]','()')
>>> s = "[1, 2, 3, 4]"
>>> s.translate(table)
'(1, 2, 3, 4)'
You can even use this to remove characters from the original string by passing an optional second argument to str.translate:
>>> s = str(['1','2'])
>>> s
"['1', '2']"
>>> s.translate(table,"'")
'(1, 2)'
In python3.x, the string module is gone and you gain access to maketrans via the str builtin:
table = str.maketrans('[]','()')
There are a billion ways to do this, as demonstrated by all the answers. Here's another one:
my_list = [1,2,3]
my_str = "(%s)" % str(my_list).strip('[]')
or make it recyclable:
list_in_parens = lambda l: "(%s)" % str(l).strip('[]')
my_str = list_in_parens(my_list)
str([1,2,3]).replace('[','(').replace(']',')')
Should work for you well, and it is forward and backward compatible as far as I know.
as far as re-usability, you can use the following function for multiple different types of strings to change what they start and end with:
def change(str_obj,start,end):
if isinstance(str_obj,str) and isinstance(start,str) and isinstance(end,str):
pass
else:
raise Exception("Error, expecting a 'str' objects, got %s." % ",".join(str(type(x)) for x in [str_obj,start,end]))
if len(str_obj)>=2:
temp=list(str_obj)
temp[0]=start
temp[len(str_obj)-1]=end
return "".join(temp)
else:
raise Exception("Error, string size must be greater than or equal to 2. Got a length of: %s" % len(str_obj))
All you need is:
"(" + strng.strip('[]') + ")"
It works for both single element and multi-element lists.
>>> lst = [1,2,3]
>>> strng = str(lst)
>>> "(" + strng.strip('[]') + ")"
'(1, 2, 3)'
>>> lst = [1]
>>> strng = str(lst)
>>> "(" + strng.strip('[]') + ")"
'(1)'
If you really want to use regex I guess this would work. But the other posted solutions are probably more efficient and/or easy to use.
import re
string = str(list)
re.sub(r"[\[]", "(", string)
re.sub(r"[\]]", ")", string)
#mgilson something like this you mean?
def replace_stuff(string):
string_list = list(string)
pattern = re.compile(r"[\[\]]")
result = re.match(pattern, string)
for i in range(len(result.groups())):
bracket = result.group(i)
index = bracket.start()
print(index)
if bracket == "[":
string_list[index] = "("
else:
string_list[index] = ")"
return str(string_list)
It doesn't quite work, for some reason len(result.groups()) is always 0 even though the regex should find matches. So couldn't test whether this is faster but because I couldn't get it to work I couldn't test it. I have to leave for bed now so if someone can fix this go ahead.
Try this:
'({0})'.format(', '.join(str(x) for x in list))
By the way, it's not a good idea to name your own variables list since it clashes with the built-in function. Also string can conflict with the module of the same name.
Assume I have a string as follows: expression = '123 + 321'.
I am walking over the string character-by-character as follows: for p in expression. I am I am checking if p is a digit using p.isdigit(). If p is a digit, I'd like to grab the whole number (so grab 123 and 321, not just p which initially would be 1).
How can I do that in Python?
In C (coming from a C background), the equivalent would be:
int x = 0;
sscanf(p, "%d", &x);
// the full number is now in x
EDIT:
Basically, I am accepting a mathematical expression from a user that accepts positive integers, +,-,*,/ as well as brackets: '(' and ')'. I am walking the string character by character and I need to be able to determine whether the character is a digit or not. Using isdigit(), I can that. If it is a digit however, I need to grab the whole number. How can that be done?
>>> from itertools import groupby
>>> expression = '123 + 321'
>>> expression = ''.join(expression.split()) # strip whitespace
>>> for k, g in groupby(expression, str.isdigit):
if k: # it's a digit
print 'digit'
print list(g)
else:
print 'non-digit'
print list(g)
digit
['1', '2', '3']
non-digit
['+']
digit
['3', '2', '1']
This is one of those problems that can be approached from many different directions. Here's what I think is an elegant solution based on itertools.takewhile:
>>> from itertools import chain, takewhile
>>> def get_numbers(s):
... s = iter(s)
... for c in s:
... if c.isdigit():
... yield ''.join(chain(c, takewhile(str.isdigit, s)))
...
>>> list(get_numbers('123 + 456'))
['123', '456']
This even works inside a list comprehension:
>>> def get_numbers(s):
... s = iter(s)
... return [''.join(chain(c, takewhile(str.isdigit, s)))
... for c in s if c.isdigit()]
...
>>> get_numbers('123 + 456')
['123', '456']
Looking over other answers, I see that this is not dissimilar to jamylak's groupby solution. I would recommend that if you don't want to discard the extra symbols. But if you do want to discard them, I think this is a bit simpler.
The Python documentation includes a section on simulating scanf, which gives you some idea of how you can use regular expressions to simulate the behavior of scanf (or sscanf, it's all the same in Python). In particular, r'\-?\d+' is the Python string that corresponds to the regular expression for an integer. (r'\d+' for a nonnegative integer.) So you could embed this in your loop as
integer = re.compile(r'\-?\d+')
for p in expression:
if p.isdigit():
# somehow find the current position in the string
integer.match(expression, curpos)
But that still reflects a very C-like way of thinking. In Python, your iterator variable p is really just an individual character that has actually been pulled out of the original string and is standing on its own. So in the loop, you don't naturally have access to the current position within the string, and trying to calculate it is going to be less than optimal.
What I'd suggest instead is using Python's built in regexp matching iteration method:
integer = re.compile(r'\-?\d+') # only do this once in your program
all_the_numbers = integer.findall(expression)
and now all_the_numbers is a list of string representations of all the integers in the expression. If you wanted to actually convert them to integers, then you could do this instead of the last line:
all_the_numbers = [int(s) for s in integer.finditer(expression)]
Here I've used finditer instead of findall because you don't have to make a list of all the strings before iterating over them again to convert them to integers.
Though I'm not familiar with sscanf, I'm no C developer, it looks like it's using format strings in a way not dissimilar to what I'd use python's re module for. Something like this:
import re
nums = re.compile('\d+')
found = nums.findall('123 + 321')
# if you know you're only looking for two values.
left, right = found
You can use shlex http://docs.python.org/library/shlex.html
>>> from shlex import shlex
>>> expression = '123 + 321'
>>> for e in shlex(expression):
... print e
...
123
+
321
>>> expression = '(92831 * 948) / 32'
>>> for e in shlex(expression):
... print e
...
(
92831
*
948
)
/
32
I'd split the string up on the ' + ' string, giving you what's outside of them:
>>> expression = '123 + 321'
>>> ex = expression.split(' + ')
>>> ex
['123', '321']
>>> int_ex = map(int, ex)
>>> int_ex
[123, 321]
>>> sum(int_ex)
444
It's dangerous, but you could use eval:
>>> eval('123 + 321')
444
I'm just taking a stab at you parsing the string, and doing raw calculations on it.
e_array = expression.split('+')
i_array = map(int, e_array)
And i_array holds all integers in the expression.
UPDATE
If you already know all the special characters in your expression and you want to eliminate them all
import re
e_array = re.split('[*/+\-() ]', expression) # all characters here is mult, div, plus, minus, left- right- parathesis and space
i_array = map(int, filter(lambda x: len(x), e_array))
This question already has answers here:
Changing one character in a string
(15 answers)
Closed last month.
I would like to read some characters from a string s1 and put it into another string s2.
However, assigning to s2[j] gives an error:
s2[j] = s1[i]
# TypeError: 'str' object does not support item assignment
In C, this works:
int i = j = 0;
while (s1[i] != '\0')
s2[j++] = s1[i++];
My attempt in Python:
s1 = "Hello World"
s2 = ""
j = 0
for i in range(len(s1)):
s2[j] = s1[i]
j = j + 1
The other answers are correct, but you can, of course, do something like:
>>> str1 = "mystring"
>>> list1 = list(str1)
>>> list1[5] = 'u'
>>> str1 = ''.join(list1)
>>> print(str1)
mystrung
>>> type(str1)
<type 'str'>
if you really want to.
In Python, strings are immutable, so you can't change their characters in-place.
You can, however, do the following:
for c in s1:
s2 += c
The reasons this works is that it's a shortcut for:
for c in s1:
s2 = s2 + c
The above creates a new string with each iteration, and stores the reference to that new string in s2.
assigning to s2[j] gives an error
Strings are immutable so what you've done in C won't be possible in Python. Instead, you'll have to create a new string.
I would like to read some characters from a string and put it into
other string.
Use a slice:
>>> s1 = 'Hello world!!'
>>> s2 = s1[6:12]
>>> print(s2)
world!
Strings in Python are immutable (you cannot change them inplace).
What you are trying to do can be done in many ways:
Copy the string:
foo = 'Hello'
bar = foo
Create a new string by joining all characters of the old string:
new_string = ''.join(c for c in oldstring)
Slice and copy:
new_string = oldstring[:]
Performant methods
If you are frequently performing index replacements, a more performant and memory-compact method is to convert to a different data structure. Then, convert back to string when you're done.
list:
Easiest and simplest:
s = "TEXT"
s = list(s)
s[1] = "_"
s = "".join(s)
bytearray (ASCII):
This method uses less memory. The memory is also contiguous, though that doesn't really matter much in Python if you're doing single-element random access anyways:
ENC_TYPE = "ascii"
s = "TEXT"
s = bytearray(s, ENC_TYPE)
s[1] = ord("_")
s = s.decode(ENC_TYPE)
bytearray (UTF-32):
More generally, for characters outside the base ASCII set, I recommend using UTF-32 (or sometimes UTF-16), which will ensure alignment for random access:
ENC_TYPE = "utf32"
ENC_WIDTH = 4
def replace(s, i, replacement):
start = ENC_WIDTH * (i + 1)
end = ENC_WIDTH * (i + 2)
s[start:end] = bytearray(replacement, ENC_TYPE)[ENC_WIDTH:]
s = "TEXT HI ひ RA ら GA が NA な DONE"
s = bytearray(s, ENC_TYPE)
# Performs s[1] = "_"
replace(s, 1, "_")
s = s.decode(ENC_TYPE)
Though this method may be more memory-compact than using list, it does require many more operations.
Other answers convert the string to a list or construct a new string character by character. These methods can be costly, especially for large strings. Instead, we can use slicing to get the parts of the string before and after the character that is changed, and combine those with the new character.
Here I modify the example code from Crowman's answer to replace a single character in the string using string slicing instead of conversion to a list.
>>> str1 = "mystring"
>>> pos = 5
>>> new_char = 'u'
>>> str2 = str1[:pos] + new_char + str1[pos+1:]
>>> print(str2)
mystrung
>>> type(str2)
<class 'str'>
Another approach if you wanted to swap out a specific character for another character:
def swap(input_string):
if len(input_string) == 0:
return input_string
if input_string[0] == "x":
return "y" + swap(input_string[1:])
else:
return input_string[0] + swap(input_string[1:])
The 'str' is an immutable data type. Therefore str type object doesn't support item assignment.
s1 = "Hello World"
s2 = ['']*len(s1)
j = 0
for i in range(len(s1)):
s2[j]=s1[i]
j = j + 1
print(''.join(s2)) # Hello World
How about this solution:
str="Hello World" (as stated in problem)
srr = str+ ""
Hi you should try the string split method:
i = "Hello world"
output = i.split()
j = 'is not enough'
print 'The', output[1], j