How to assign two values in for loop variable - python

how can we use for loop to assign two values from the string like following
string="abcd"
for i in string:
print(i)
this will give i one value from the string
#output
a
b
c
d
how can i take two values like ab and cd. I know we can do this in print but i need to assign two values in "i"
I need output
#output
ab
cd

You could use list-comprehension like the following:
n = 2
s = "abcd"
res = [s[i:i+n] for i in range(0, len(s), n)]
print(res) # ['ab', 'cd']
This is applicable to any nth place.
If its only 2 chars that you are after you can also use regex, but if it for any n its not convenient, an example for n=2 is:
import re
s = "abcd"
res = re.findall('..?',s)
print(res) # ['ab', 'cd']

Try this:
string = "abcd"
for i in range(1,len(string),2):
print(string[i-1]+string[i])
Output:
ab
cd
Explanation
You can modify the range function to start at index 1 and go all the way through len(string) in steps of 2(range(1,len(string),2))
Then inside the loop, since we start index 1, we print string[i-1] and concatenate with string[i]

Related

String manipulation with python and storing alphabets and digits in separate lists

For a given string s='ab12dc3e6' I want to add 'ab' and '12' in two different lists. that means for output i am trying to achieve as temp1=['ab','dc','e'] and for temp2=['12,'3','6'].
I am not able to do so with the following code. Can someone provide an efficient way to do it?
S = "ab12dc3e6"
temp=list(S)
x=''
temp1=[]
temp2=[]
for i in range(len(temp)):
while i<len(temp) and (temp[i] and temp[i+1]).isdigit():
x+=temp[i]
i+=1
temp1.append(x)
if not temp[i].isdigit():
break
You can also solve this without any imports:
S = "ab12dc3e6"
def get_adjacent_by_func(content, func):
"""Returns a list of elements from content that fullfull func(...)"""
result = [[]]
for c in content:
if func(c):
# add to last inner list
result[-1].append(c)
elif result[-1]: # last inner list is filled
# add new inner list
result.append([])
# return only non empty inner lists
return [''.join(r) for r in result if r]
print(get_adjacent_by_func(S, str.isalpha))
print(get_adjacent_by_func(S, str.isdigit))
Output:
['ab', 'dc', 'e']
['12', '3', '6']
you can use regex, where you group letters and digits, then append them to lists
import re
S = "ab12dc3e6"
pattern = re.compile(r"([a-zA-Z]*)(\d*)")
temp1 = []
temp2 = []
for match in pattern.finditer(S):
# extract words
#dont append empty match
if match.group(1):
temp1.append(match.group(1))
print(match.group(1))
# extract numbers
#dont append empty match
if match.group(2):
temp2.append(match.group(2))
print(match.group(2))
print(temp1)
print(temp2)
Your code does nothing for isalpha - you also run into IndexError on
while i<len(temp) and (temp[i] and temp[i+1]).isdigit():
for i == len(temp)-1.
You can use itertools.takewhile and the correct string methods of str.isdigit and str.isalpha to filter your string down:
S = "ab12dc3e6"
r = {"digit":[], "letter":[]}
from itertools import takewhile, cycle
# switch between the two test methods
c = cycle([str.isalpha, str.isdigit])
r = {}
i = 0
while S:
what = next(c) # get next method to use
k = ''.join(takewhile(what, S))
S = S[len(k):]
r.setdefault(what.__name__, []).append(k)
print(r)
Output:
{'isalpha': ['ab', 'dc', 'e'],
'isdigit': ['12', '3', '6']}
This essentially creates a dictionary where each seperate list is stored under the functions name:
To get the lists, use r["isalpha"] or r["isdigit"].

how to I return the index of multiple characters in a string when running a for loop?

I have the following code:
dup = ["aaa","bbb","ccc"]
s = "hfidgfaaahjfihdfhd"
for duplicate in dup:
if duplicate in s:
print(s.index(duplicate))
The output is 6; which is the index of the first character of "aaa" in the string s, however, I would like it to print all three of its indexes, i.e. 6,7,8.
Is there anyway I can tweak the code to achieve this?
Probably, the easiest tweak you could do is: instead of printing just the index of the duplicate, print all the numbers starting from the index of the duplicate up to index of the duplicate + length of the duplicate, like this:
dup = ["aaa","bbb","ccc"]
s = "hfidgfaaahjfihdfhd"
for duplicate in dup:
if duplicate in s:
print(*list(range(s.index(duplicate), s.index(duplicate) + len(duplicate))))
Here, I am using the list(range()) function to generate a list of all the numbers within the range s.index(duplicate) up to (but not included!) s.index(duplicate) + len(duplicate).
The asterisk at the beginning is used to unpack the list and print each value individually instead of printing it as a list: without the asterisk, you would get [6, 7, 8]. With the asterisk, you should get exactly 6 7 8.
An easier alternative, but with the exact same logic, would be this:
dup = ["aaa","bbb","ccc"]
s = "hfidgfaaahjfihdfhd"
for duplicate in dup:
if duplicate in s:
for index in range(s.index(duplicate), s.index(duplicate) + len(duplicate)):
print(index)
You can avoid the *list(range()) using a regular for loop with the range function
Well, you can do it by this way:
dup = ['aaa', 'bbb', 'ccc']
s = "hhdahwhdaaadfewfeas"
for i in range(0, len(s), len(dup[0]) - 1):
string_to_check = s[i:3+i:]
if dup[0] == string_to_check:
for j in range(0, len(string_to_check)):
print(f'Index for the letters: {j + i}')
I would suggest using regular expressions (re) for this (in particular Match.span()):
import re
dup = ["aaa", "bbb", "ccc"]
s = "hfidgfaaahjfihdfhd"
for duplicate in dup:
# finditer returns an iterator over all found matches
matches = re.finditer(duplicate, s)
for match in matches:
# The span() method returns a tuple containing
# the start and end position of the match.
# These can be passed into the built-in range() function
# to generate the indices you are interested in:
print(f"Match for '{duplicate}':", *range(*match.span()))
Will print:
Match for 'aaa': 6 7 8
If you now changed s to "hfidgfaaahjfihdfhdaaabbb", the result would be:
Match for 'aaa': 6 7 8
Match for 'aaa': 18 19 20
Match for 'bbb': 21 22 23

Cut character string every two commas

I would like to separate my string every both commas but I can not, can you help me.
This is what I want: ['nb1,nb2','nb3,nb4','nb5,nb6']
Here is what I did :
a= 'nb1,nb2,nb3,nb4,nb5,nb6'
compteur=0
for i in a:
if i==',' :
compteur+=1
if compteur%2==0:
print compteur
test = a.split(',', compteur%2==0 )
print a
print test
The result:
2
4
nb1,nb2,nb3,nb4,nb5,nb6
['nb1', 'nb2,nb3,nb4,nb5,nb6']
Thanks you by advances for you answers
You can use regex
In [12]: re.findall(r'([\w]+,[\w]+)', 'nb1,nb2,nb3,nb4,nb5,nb6')
Out[12]: ['nb1,nb2', 'nb3,nb4', 'nb5,nb6']
A quick fix could be to simply first separate the elements by commas and then join the elements by two together again. Like:
sub_result = a.split(',')
result = [','.join(sub_result[i:i+2]) for i in range(0,len(sub_result),2)]
This gives:
>>> result
['nb1,nb2', 'nb3,nb4', 'nb5,nb6']
This will also work if the number of elements is odd. For example:
>>> a = 'nb1,nb2,nb3,nb4,nb5,nb6,nb7'
>>> sub_result = a.split(',')
>>> result = [','.join(sub_result[i:i+2]) for i in range(0,len(sub_result),2)]
>>> result
['nb1,nb2', 'nb3,nb4', 'nb5,nb6', 'nb7']
You use a zip operation of the list with itself to create pairs:
a = 'nb1,nb2,nb3,nb4,nb5,nb6'
parts = a.split(',')
# parts = ['nb1', 'nb2', 'nb3', 'nb4', 'nb5', 'nb6']
pairs = list(zip(parts, parts[1:]))
# pairs = [('nb1', 'nb2'), ('nb2', 'nb3'), ('nb3', 'nb4'), ('nb4', 'nb5'), ('nb5', 'nb6')]
Now you can simply join every other pair again for your output:
list(map(','.join, pairs[::2]))
# ['nb1,nb2', 'nb3,nb4', 'nb5,nb6']
Split the string by comma first, then apply the common idiom to partition an interable into sub-sequences of length n (where n is 2 in your case) with zip.
>>> s = 'nb1,nb2,nb3,nb4,nb5,nb6'
>>> [','.join(x) for x in zip(*[iter(s.split(','))]*2)]
['nb1,nb2', 'nb3,nb4', 'nb5,nb6']

How to find a index of an item in a string?

But I need the index of the second time appearance.
It is like I have a string "asd#1-2#qwe"
I can simply use index method to find the index value of first #, which is 3.
But now I wanna get the index of second #, which should be 7.
Use enumerate and a list comprehension:
>>> s = "asd#1-2#qwe"
>>> [i for i, c in enumerate(s) if c=='#']
[3, 7]
Or if string contains just two '#' then use str.rfind:
>>> s.rfind('#')
7
Using regex: This will work for overlapping sub-strings as well:
>>> s = "asd##1-2####qwe"
>>> import re
#Find index of all '##' in s
>>> [m.start() for m in re.finditer(r'(?=##)', s)]
[3, 8, 9, 10]
use this:
s = "asd#1-2#qwe"
try:
s.index('#',s.index('#')+1)
except:
print "not found"
Use the index method to get the first occurrence of #. If the index method allows a starting position, use the position of the first # + 1 for the start. If it doesn't, make a copy of the string starting at position of first # + 1 (possibly a copy and then a substring).
a = "asd#1-2#qwe"
f = '#'
idx = []
for i, v in enumerate(a):
if v == f:
idx.append(i)
print idx

how to insert item from one list to other at position which doesnot contains alphanumeric

these are my lists
i=["a","b"]
j=["abc","(3)","ab & ac", "(1,4)","xyz"]
and I want my output be like this
j=["abc","a","ab & ac","b","xyz"]
and i tried like this,
val=0
for item in j:
if item.isalpha():
pass
else:
elem=i[val]
j.replace(item, elem)
val=val+1
How to insert item from one list to other at position which does not contains alphanumeric?
Assuming that "ab & ac" is not alphanumeric (because of the & and whitespaces) and that you made a typo, this will do the trick.
def removeNonAlpha(i,j):
indexI = 0
indexJ = 0
while indexJ < len(j):
if not j[indexJ].isalnum():
j[indexJ] = i[indexI]
indexI += 1
indexJ += 1
return j
>>>i=["a","b", "c"]
>>>j=["abc","(3)","ab & ac", "(1,4)","xyz"]
>>>removeNonAlpha(i,j)
['abc', 'a', 'b', 'c', 'xyz']
This code also assumes that you have enough elements in i to make complete replacements for j.
If for some special reasons you need to allow & signs (which would imply that you would also need to allow the whitespaces) here is the alternative:
def removeNonAlpha(i,j):
indexI = 0
indexJ = 0
while indexJ < len(j):
if not j[indexJ].replace('&', '').replace(' ', '').isalnum():
j[indexJ] = i[indexI]
indexI += 1
indexJ += 1
return j
>>>i=["a","b"]
>>>j=["abc","(3)","ab & ac", "(1,4)","xyz"]
>>>removeNonAlpha(i,j)
['abc', 'a', 'ab & ac', 'b', 'xyz']
This will preserve any list element in a list j that has a letter in it
[s for s in j if any(c in string.letters for c in s)]
If you have a character or string than doesn't occur in any of the strings, you can concatenate the list into a single string using the string .join method, then use a regular expression and the re.sub function to do the replacement. After that, you can use the .split method to divide the string back into a list:
>>> import re
>>> i=["a","b"]; j=["abc","(3)","ab & ac", "(1,4)","xyz"]
>>> js = "|".join(j) # merge j into one string
>>> print js
abc|(3)|ab & ac|(1,4)|xyz
>>> print re.sub("\(.*?\)", i[0], js)
abc|a|ab & ac|a|xyz
>>> print re.sub("\(.*?\)", i[0], js, count=1)
abc|a|ab & ac|(1,4)|xyz
>>> for r in i:
js = re.sub("\(.*?\)", r, js, count=1)
>>> print js
abc|a|ab & ac|b|xyz
That for loop at the end shows you how to do it. The parenthesized fields will be filled in, one at a time, from left to right. To put it back into a list:
jnew = js.split("|")
...and you're done.
It's not clear what your definition of "alphanumeric" is. Your example uses isalpha, which "ab & ac" fails, as DSM pointed out. If isalpha is an acceptable definition of "alphanumeric", and it's OK to modify the arrays, then I propose the following:
for index, item in enumerate(j):
if not item.isalpha():
j[index] = i.pop(0) if i else None
There's probably a list comprehension version of this, but it would be messy.
Note that the above code produces the following result, given your sample inputs:
['abc', 'a', 'b', None, 'xyz']
That's because there aren't actually enough items in i to cover all the non-alphanumeric members of j, so I used None in that case.

Categories

Resources