In Groovy Language How to replace a character in a string based on the value and position in the string - string

I am looking to amend the values of a string IF certain positions within a string are certain values for example I have a postcode L65 OBH and I need to do the following:
(1)
If the 1st value in the first section of the string (split by white space) = L it needs to be changed to T. This would then give:
T65 OBH
(2)
Then if the 2nd value in the first section of the string (split by white space) = 6 it needs to be changed to 7. This would then give:
T75 OBH
(3)
Then if the 1st value in the second section of the string (split by white space) = O it needs to be changed to 2. This would then give:
T75 2BH
(4)
Then if the 3rd value in the second section of the string (split by white space) = H it needs to be changed to P. This would then give:
T75 2BP
I'm assuming that I need to use replaceall and a number of IF statements but I am struggling to work this out, particularly how to split the 2 different parts of the postcode out treat them as separate enteties....can anyone help please

I'd write a helper method for the replacement rules:
def postcode = 'L65 0BH'
def (first, second) = postcode.split(/\s+/)
def replaceIf(String token, int position, String match, String replacement) {
(0..<token.length()).collect { index ->
if(index == position && token[index] == match) {
replacement
}
else {
token[index]
}
}.join()
}
first = replaceIf(first, 0, 'L', 'T')
first = replaceIf(first, 1, '6', '7')
second = replaceIf(second, 0, '0', '2')
second = replaceIf(second, 2, 'H', 'P')
assert "$first $second" == 'T75 2BP'

def strVal= "L65 OBH"
strVal.replaceFirst(/^L/, "T")
def strVal1= "L65 OBH"
strVal1.replaceFirst(/^6/, "7")
and so on using the same replaceFirst() method

Related

How to get the index of a character in a String in Scala?

If I have a String an I am looping through that String looking at each character, how do I get the index of that character in that String?
I have seen people use "indexOf()" however when I see them use this it only returns the index of the first occurrence of that character. But what if there are multiple occurrences of that same character? How do I get the index of the character I am currently looking at?
I began using:
for(c <- str)
to look at each character individually.
It's not quite clear why you need to get the index of the character you are currently iterating over, since because you are iterating, you already know what the index is (all you have to do is to keep count). For example, something like this:
val str = "Hello World"
for ((c, i) ← str.zipWithIndex) println(s"$c is at $i")
// H is at 0
// e is at 1
// l is at 2
// l is at 3
// o is at 4
// is at 5
// W is at 6
// o is at 7
// r is at 8
// l is at 9
// d is at 10
You can use zipWithIndex() together with filter() to search for an index.
val str = "12334563"
str.toList.zipWithIndex.filter((x) => x._1 == '3')
res9: List[(Char, Int)] = List(('3', 2), ('3', 3), ('3', 7))
If required you can also remove the toList() call.
Well... there are methods which can get this done for you, but lets say there was no such method... even then you can do this by using entry level programming.
val string: String = "my awesome string"
val char: Char = 'e'
Now, the most basic solution,
var index = 0
val indexListBuffer: ListBuffer[Int] = ListBuffer()
for (c <- string) {
if (c == char) {
indexListBuffer.append(index)
}
index = index + 1
}
println(indexListBuffer)

Check if text contains a string and keep matched words from original text:

a = "Beauty Store is all you need!"
b = "beautystore"
test1 = ''.join(e for e in a if e.isalnum())
test2 = test1.lower()
test3 = [test2]
match = [s for s in test3 if b in s]
if match != []:
print(match)
>>>['beautystoreisallyouneed']
What I want is: "Beauty Store"
I search for the keyword in the string and I want to return the keyword from the string in the original format (with capital letter and space between, whatever) of the string, but only the part that contains the keyword.
If the keyword only occurs once, this will give you the right solution:
a = "Beauty Store is all you need!"
b = "beautystore"
ind = range(len(a))
joined = [(letter, number) for letter, number in zip(a, ind) if letter.isalnum()]
searchtext = ''.join(el[0].lower() for el in joined)
pos = searchtext.find(b)
original_text = a[joined[pos][1]:joined[pos+len(b)][1]]
It saves the original position of each letter, joins them to the lowercase string, finds the position and then looks up the original positions again.

Create a list of strings with one/multiple character replacement

How to create a whole list of string from one string where each string in the list containing exactly one character replacement? The string itself is consisted of only four characters (say: A, B, C, and D), so that the whole list of a string of length n would contain 3n+1 strings with exactly one character replacement.
Example:
inputstr = 'ABCD'
output = ['ABCD', 'BBCD', 'CBCD', 'DBCD', 'AACD', 'ACCD', 'ADCD', 'ABAD', 'ABBD', 'ABDD', 'ABCA', 'ABCB', 'ABCC']
I write the following python code:
strin = 'ABCD'
strout = set()
tempstr1 = ''
tempstr2 = ''
tempstr3 = ''
tempstr4 = ''
for base in range(len(strin)):
if strin[base] == 'A': #this block will be repeated for char B, C and D
tempstr1 = strin.replace(strin[base], 'A')
strout.add(tempstr1)
tempstr1 = ''
tempstr2 = strin.replace(strin[base], 'B')
strout.add(tempstr2)
tempstr2 = ''
tempstr3 = strin.replace(strin[base], 'C')
strout.add(tempseq3)
tempstr3 = ''
tempstr4 = strin.replace(strin[base], 'D')
strout.add(tempseq4)
tempstr4 = ''
return strout
and it works well as long as there is no repeated character (such as 'ABCD'). However, when the input string contains repeated character (such as 'AACD'), it will return less than 3n+1 string. I tried with 'AACD' string and it returns only 10 instead of 13 strings.
Anyone can help?
change
strout = set() ===> strout = list()
I found it. I used a slicing method to create a list of total combination of strings with one replacement.
for i in range(len(seq)):
seqxlist.append(seq[:i] + 'x' + seq[i+1:])
and after that I filter out all the x-replaced strings which are longer than the original string length:
seqxlist = [x for x in seqxlist if (len(x) == len(seq))]
Then, I changed x into any of the substitution characters:
for m in seqxlist:
tempseq1 = m.replace('x', 'A')
outseq.append(tempseq1)
tempseq2 = m.replace('x', 'B')
outseq.append(tempseq2)
tempseq3 = m.replace('x', 'C')
outseq.append(tempseq3)
tempseq4 = m.replace('x', 'D')
outseq.append(tempseq4)
This will create all the possible combinations of string replacement, but still contains duplicates. To remove duplicates, I use set() to the outseq list.

Zipping strings together at arbitrary index and step (Python)

I am working in Python 2.7. I am trying to create a function which can zip a string into a larger string starting at an arbitrary index and with an arbitrary step.
For example, I may want to zip the string ##*#* into the larger string TNAXHAXMKQWGZESEJFPYDMYP starting at the 5th character with a step of 3. The resulting string should be:
TNAXHAX#MK#QW*GZ#ES*EJFPYDMYP
The working function that I came up with is
#Insert one character of string every nth position starting after ith position of text
text="TNAXHAXMKQWGZESEJFPYDMYP"
def zip_in(string,text,i,n):
text=list(text)
for c in string:
text.insert(i+n-1,c)
i +=n
text = ''.join(text)
print text
This function produces the desired result, but I feel that it is not as elegant as it could be.
Further, I would like it to be general enough that I can zip in a string backwards, that is, starting at the ith position of the text, I would like to insert the string in one character at a time with a backwards step.
For example, I may want to zip the string ##*#* into the larger string TNAXHAXMKQWGZESEJFPYDMYP starting at the 22nd position with a step of -3. The resulting string should be:
TNAXHAXMKQW*GZ#ES*EJ#FP#YDMYP
With my current function, I can do this by setting n negative, but if I want a step of -3, I need to set n as -2.
All of this leads me to my question:
Is there a more elegant (or Pythonic) way to achieve my end?
Here are some related questions which don't provide a general answer:
Pythonic way to insert every 2 elements in a string
Insert element in Python list after every nth element
Merge Two strings Together at N & X
You can use some functions from the itertools and more_itertools libraries (make sure to have them) and combine them to get your result : chunked and izip_longest.
# Parameters
s1 = 'ABCDEFGHIJKLMNOPQ' # your string
s2 = '####' # your string of elements to add
int_from = 4 # position from which we start adding letters
step = 2 # we will add in elements of s2 each 2 letters
return_list = list(s1)[:int_from] # keep the first int_from elements unchanged
for letter, char in izip_longest(chunked(list(s1)[int_from:], step), s2, fillvalue=''):
return_list.extend(letter)
return_list.append(char)
Then get your string back by doing :
''.join(return_list)
Output :
# For the parameters above the output is :
>> 'ABCDEF#GH#IJ#KL#MNOPQ'
What does izip_longest(chunked(list(s1)[int_from:], step), s2, fillvalue='') return ?:
for letter, char in izip_longest(chunked(list(s1)[int_from:], step), s2, fillvalue=''):
print(letter, char)
>> Output
>> (['E', 'F'], '#')
(['G', 'H'], '#')
(['I', 'J'], '#')
(['K', 'L'], '#')
(['M', 'N'], '')
(['O', 'P'], '')
(['Q'], '')

python3 sum in stings each letter value

i need sum in string letters value ex.
a = 1
b = 2
c = 3
d = 4
alphabet = 'abcdefghijklmnopqrstuvwxyz'
v1
string = "abcd"
# #result = sum(string) so
if string[0] and string[1] and string[2] and string[3] in alphabet:
if string[0] is alphabet[0] and string[1] is alphabet[1] and string[2] is alphabet[2] and string[3] is alphabet[3]:
print(a+b+c+d)
v2
string = ("ab","aa","dc",)
if string[0][0] and string[0][1] and string[1][0] and string[1][1] and string[2][0] and string[2][1] in alphabet:
if string[0] is alphabet[0] and string[1] is alphabet[1] and string[2] is alphabet[2] and string[3] is alphabet[3]:
print(a+b+c+d)
what is the solution? can you help me
Use the sum() function and a generator expression; a dictionary built from string.ascii_lowercase can serve as a means to getting an integer value per letter:
from string import ascii_lowercase
letter_value = {c: i for i, c in enumerate(ascii_lowercase, 1)}
wordsum = sum(letter_value.get(c, 0) for c in word if c)
The enumerate(ascii_lowercase, 1) produces (index, letter) pairs when iterated over, starting at 1. That gives you (1, 'a'), (2, 'b'), etc. That can be converted to c: i letter pairs in a dictionary, mapping letter to integer number.
Next, using the dict.get() method lets you pick a default value; for any character in the input string, you get to look up the numeric value and map it to an integer, but if the character is not a lowercase letter, 0 is returned instead. The sum(...) part with the loop then simply adds those values up.
If you need to support sequences with words, just use sum() again. Put the above sum() call in a function, and apply that function to each word in a sequence:
from string import ascii_lowercase
letter_value = {c: i for i, c in enumerate(ascii_lowercase, 1)}
def sum_word(word):
return sum(letter_value.get(c, 0) for c in word if c)
def sum_words(words):
return sum(sum_word(word) for word in words)
The old-fashioned way is to take advantage of the fact that lowercase letters are contiguous, so that ord(b) - ord(a) == 1:
data = "abcd"
print("Sum:", sum(ord(c)-ord("a")+1 for c in data))
Of course you could "optimize" it to reduce the number of computations, though it seems silly in this case:
ord_a = ord("a")
print("Sum:", sum(ord(c)-ord_a for c in data)+len(data))

Resources