Python string to list per character - python

Good day I just want to understand the logic behind this code
lst = []
word = "ABCD"
lst[:0] = word
print(lst)
OUTPUT: ['A', 'B', 'C', 'D'] why not ['ABCD'] how?
for i in word: # this code I understand it's looping through the string
lst.append(i) # then appending to list
but the first code above I don't get the logic.

lst[:0] = ... is implemented by lst.__setitem__(slice(0, None, 0), ...), where ... is an arbitrary iterable.
The resulting slice is the empty list at the beginning of lst (though in this case, it doesn't really matter since lst is empty), so each element of ... is inserted into lst, starting at the beginning.
You can see this starting with a non-empty list.
>>> lst = [1,2,3]
>>> word = "ABCD"
>>> lst[:0] = word
>>> lst
['A', 'B', 'C', 'D', 1, 2, 3]
To get lst == ['ABCD'], you need to make the right-hand side an iterable containing the string:
lst[:0] = ('ABCD', ) # ['ABCD'] would also work.

Actually it's a well known way to convert string to a list character by character
you can find here -> https://www.geeksforgeeks.org/python-program-convert-string-list/
if you wanna try to get your list element like 'ABCD' then try
lst[:0] = [word,]
by doing that you specify that you need whole word as an element

Related

How to do slicing in strings in python?

I am trying to do slicing in string "abcdeeefghij", here I want the slicing in such a way that whatever input I use, i divide the output in the format of a list (such that in one list element no alphabets repeat).
In this case [abcde,e,efghij].
Another example is if input is "aaabcdefghiii". Here the expected output is [a,a,acbdefghi,i,i].
Also amongst the list if I want to find the highest len character i tried the below logic:
max_str = max(len(sub_strings[0]),len(sub_strings[1]),len(sub_strings[2]))
print(max_str) #output - 6
which will yield 6 as the output, but i presume this logic is not a generic one: Can someone suggest a generic logic to print the length of the maximum string.
Here is how:
s = "abcdeeefghij"
l = ['']
for c in s: # For character in s
if c in l[-1]: # If the character is already in the last string in l
l.append('') # Add a new string to l
l[-1] += c # Add the character to either the last string, either new, or old
print(l)
Output:
['abcde', 'e', 'efghij']
Use a regular expression:
import re
rx = re.compile(r'(\w)\1+')
strings = ['abcdeeefghij', 'aaabcdefghiii']
lst = [[part for part in rx.split(item) if part] for item in strings]
print(lst)
Which yields
[['abcd', 'e', 'fghij'], ['a', 'bcdefgh', 'i']]
You would loop over the characters in the input and start a new string if there is an existing match, otherwise join them onto the last string in the output list.
input_ = "aaabcdefghiii"
output = []
for char in input_:
if not output or char in output[-1]:
output.append("")
output[-1] += char
print(output)
To avoid repetition of alphabet within a list element repeat, you can greedily track what are the words that are already in the current list. Append the word to your answer once you detected a repeating alphabet.
from collections import defaultdict
s = input()
ans = []
d = defaultdict(int)
cur = ""
for i in s:
if d[i]:
ans.append(cur)
cur = i # start again since there is repeatition
d = defaultdict(int)
d[i] = 1
else:
cur += i #append to cur since no repetition yet
d[i] = 1
if cur: # handlign the last part
ans.append(cur)
print(ans)
An input of aaabcdefghiii produces ['a', 'a', 'abcdefghi', 'i', 'i'] as expected.

Python - change text in string by random from a list

I want to write a loop function that go through each letter in my list called original.
original = ['ABCD', 'DCBA', 'AAAA', 'AABB']
letters = ['A', 'B', 'C', 'D']
p = 1
for o in original: # loop through the original list
for i in range(0,len(o)): # loop through each letter in selected list
if random.randint(1,10) == p: #if this gives me the probability that is met
# I want to change the current letter on the current index to
# something else different from the letter list by random (maybe random.choice)
Im new to python please can you advice.
I dont want to use class or any other library but random please
First, the zero in
for i in range(0, len(o))
is redundant. You want to give random.choice a list of letters that include everything in letters minus the current letter. The fastest way I can think of doing this is with a set:
newletters = list(set(letters).difference(o[i])
Now you have a list that includes all the letters in "letters" except for the letter at o[i].
To assign the letter (after you get it from random.choice), turn your "original" word into a list:
o_list = list(o)
and assign it as
l = random.choice(newletters)
o_list[i] = l
new_word = "".join(o_list)
As for actually inserting that new word back into your list of originals, you would have to know the index of the old word - I would use enumerate to do this:
original = ['ABCD', 'DCBA', 'AAAA', 'AABB']
letters = ['A', 'B', 'C', 'D']
p = 1
for index, o in enumerate(original): # loop through the original list
for i in range(len(o)): # loop through each letter in selected list
if random.randint(1,10) == p:
newletters = list(set(letters).difference(o[i])
o_list = list(o)
l = random.choice(newletters)
o_list[i] = l
new_word = "".join(o_list)
original[index] = new_word
In python, you can not modify strings at all. You can get letters by index, select specific strings, but not modify them. To change the said list you can use original.pop(o) and add the said edited string in the list with original.append('AB" + random.choice(letters) + 'C' as you said. To be more clear: you use list.append(element) to add element to list and you use list.pop(element) to remove element from list. Again, you can never edit strings in python, you can only create new ones and store the edited old ones, for example, new_string = old_string[:4], this particular code will store all the characters in old_string, up to index 4 into the new string. Really hope I helped!
Assuming you want to update original
import random
original = ['ABCD', 'DCBA', 'AAAA', 'AABB']
letters = ['A', 'B', 'C', 'D']
p = 1
for i, o in enumerate(original):
new_letters = [] # updated letters for word o
for c in o:
if random.randint(1,10) == p:
t = letters[:] # copy of letters
t.remove(c) # remove letter from copy (so letters remains unchanged)
new_letters.append(random.choice(t)) # choice over remaining letters
else:
new_letters.append(c)
original[i] = ''.join(new_letters) # convert newsletters list to string
# and replace in original
print(original)

Creating a list of lists with regular expressions in python

I thought I had successfully created and filtered a list of lists using regular expression in python. However, when I attempt to index the lists I just index the first item in each of the lists. Upon closer inspection I noticed that I don't have any commas between my lists. I'm wondering how I can turn each of these individual lists into a list of lists?
I want to do this so that I can reference the different lists and state whether the lists meets a specific criteria.
import re
list_of_strings = ['''<z><x><c></v></b></n>''',
'''<paa>mnb<ore>mnbczx</bar><e>poiuy</e></paa>''',
'''<paa><ore></lan></ore></paa>''',
'''<paa><ore></ore></paa></paa>''',
'''<paa><ore></paa></ore>''']
def valid_html(list_of_strings):
matches = [[s] for s in list_of_strings]
lst = []
for item in matches:
tagsRegex = re.compile(r'(<.{0,3}>|</.{0,3}>)')
lst = (tagsRegex.findall(str(item)))
find = re.compile(r'(<)|(>)')
no_tags = [find.sub('', t) for t in lst]
print(no_tags)
print(no_tags[0])
valid_html(test_strings)
My output is:
valid_html(test_strings)
['z', 'x', 'c', '/v', '/b', '/n']
z
['paa', 'ore', '/ore', 'e', '/e', '/paa']
paa
['paa', 'ore', '/lan', '/ore', '/paa']
paa
['paa', 'ore', '/ore', '/paa', '/paa']
paa
['paa', 'ore', '/paa', '/ore']
paa
Thank you for your time!
You are inserting inside the loop and printing inside the loop. You need to print outside the for loop of need to return the same
def valid_html(list_of_strings):
matches = [[s] for s in list_of_strings]
lst = []
l=[]
for item in matches:
tagsRegex = re.compile(r'(<.{0,3}>|</.{0,3}>)')
lst = (tagsRegex.findall(str(item)))
find = re.compile(r'(<)|(>)')
no_tags = [find.sub('', t) for t in lst]
l.append(no_tags)
return l
valid_html(list_of_strings)[0]

most pythonic way to compare substrings l in list L to string S & edit S according to l in L?

The list ['a','a #2','a(Old)'] should become {'a'} because '#' and '(Old)' are to be excised and a list of duplicates isn't needed. I struggled to develop a list comprehension with a generator and settled on this since I knew it'd work and valued time more than looking good:
l = []
groups = ['a','a #2','a(Old)']
for i in groups:
if ('#') in i: l.append(i[:i.index('#')].strip())
elif ('(Old)') in i: l.append(i[:i.index('(Old)')].strip())
else: l.append(i)
groups = set(l)
What's the slick way to get this result?
Here is general solution, if you want to clean elements of list lst from parts in wastes:
lst = ['a','a #2','a(Old)']
wastes = ['#', '(Old)']
cleaned_set = {
min([element.split(waste)[0].strip() for waste in wastes])
for element in arr
}
You could write this whole expression in a single set comprehension
>>> groups = ['a','a #2','a(Old)']
>>> {i.split('#')[0].split('(Old)')[0].strip() for i in groups}
{'a'}
This will get everything preceding a # and everything preceding '(Old)', then trim off whitespace. The remainder is placed into a set, which only keeps unique values.
You could define a helper function to apply all of the splits and then use a set comprehension.
For example:
lst = ['a','a #2','a(Old)', 'b', 'b #', 'b(New)']
splits = {'#', '(Old)', '(New)'}
def split_all(a):
for s in splits:
a = a.split(s)[0]
return a.strip()
groups = {split_all(a) for a in lst}
#{'a', 'b'}

Python: Append double items to new array

lets say I have an array "array_1" with these items:
A b A c
I want to get a new array "array_2" which looks like this:
b A c A
I tried this:
array_1 = ['A','b','A','c' ]
array_2 = []
for item in array_1:
if array_1[array_1.index(item)] == array_1[array_1.index(item)].upper():
array_2.append(array_1[array_1.index(item)+1]+array_1[array_1.index(item)])
The problem: The result looks like this:
b A b A
Does anyone know how to fix this? This would be really great!
Thanks, Nico.
It's because you have 2 'A' in your array. In both case for the 'A',
array_1[array_1.index(item)+1
will equal 'b' because the index method return the first index of 'A'.
To correct this behavior; i suggest to use an integer you increment for each item. In that cas you'll retrieve the n-th item of the array and your program wont return twice the same 'A'.
Responding to your comment, let's take back your code and add the integer:
array_1 = ['A','b','A','c' ]
array_2 = []
i = 0
for item in array_1:
if array_1[i] == array_1[i].upper():
array_2.append(array_1[i+1]+array_1[i])
i = i + 1
In that case, it works but be careful, you need to add an if statement in the case the last item of your array is an 'A' for example => array_1[i+1] won't exist.
I think that simple flat list is the wrong data structure for the job if each lower case letter is paired with the consecutive upper case letter. If would turn it into a list of two-tuples i.e.:
['A', 'b', 'A', 'c'] becomes [('A', 'b'), ('A', 'c')]
Then if you are looping through the items in the list:
for item in list:
print(item[0]) # prints 'A'
print(item[1]) # prints 'b' (for first item)
To do this:
input_list = ['A', 'b', 'A', 'c']
output_list = []
i = 0;
while i < len(input_list):
output_list.append((input_list[i], input_list[i+1]))
i = i + 2;
Then you can swap the order of the upper case letters and the lower case letters really easily using a list comprehension:
swapped = [(item[1], item[0]) for item in list)]
Edit:
As you might have more than one lower case letter for each upper case letter you could use a list for each group, and then have a list of these groups.
def group_items(input_list):
output_list = []
current_group = []
while not empty(input_list):
current_item = input_list.pop(0)
if current_item == current_item.upper():
# Upper case letter, so start a new group
output_list.append(current_group)
current_group = []
current_group.append(current_item)
Then you can reverse each of the internal lists really easily:
[reversed(group) for group in group_items(input_list)]
According to your last comment, you can get what you want using this
array_1 = "SMITH Mike SMITH Judy".split()
surnames = array_1[1::2]
names = array_1[0::2]
print array_1
array_1[0::2] = surnames
array_1[1::2] = names
print array_1
You get:
['SMITH', 'Mike', 'SMITH', 'Judy']
['Mike', 'SMITH', 'Judy', 'SMITH']
If I understood your question correctly, then you can do this:
It will work for any length of array.
array_1 = ['A','b','A','c' ]
array_2 = []
for index,itm in enumerate(array_1):
if index % 2 == 0:
array_2.append(array_1[index+1])
array_2.append(array_1[index])
print array_2
Output:
['b', 'A', 'c', 'A']

Categories

Resources