I'm using a for loop and it concatenates a string as such:
list1 = ["Hi","There"]
final = ""
for item in list1:
final += item + "\n"
It prints out:
Hi
There
#extra space here instead of comment
Now I know the solution where you do for i in range(len(list1)) and then you use "i" in an if statement to check if it's the last line, but this is problematic for me in my bigger case (which is not shown here).
What are some other alternatives to getting rid of the extra blankline? Like a trim or regex? I don't know, just suggestions.
You can use join to insert newlines only between each element of the list:
final = '\n'.join(list1)
Or you can use strip on the output of your loop:
list1 = ["Hi","There"]
final = ""
for item in list1:
final += item + "\n"
final = final.strip()
you can use end=""
Suppose a is a list
eg: print(a,end="")
Related
I am trying to use list comprehension to cycle through the letters in a word and get new combinations after removing one letter at a time.
E.g. say the input string is a word: 'bathe'
I would like to get the output in a list (preferably) with the following
[athe, bthe, bahe, bate]
ie, making just one pass from left to right
---- this is the literal, but I need to accomplish this with list comprehension
word = "bathe"
newlist1 = [word[1::], (word[1:2] + word[-3:]), (word[:2] + word[-2:]), word[:3] + word[-1:] ]
print('sample 1', newlist1)
newlist2 = [(word[1:2] + word[-3:]), (word[1:2] + word[-3:]), (word[:2] + word[-2:]), word[:3] + word[-1:] ]
print('sample 2', newlist2)
I got through the first pass with this code, but am stuck now
x = [(word[:i] + word[-j:]) for i in range(1,4) for j in range(4,1, -1)]
The output I get is obviously not right, but (hopefully) is directionally there (when it comes to using list comprehensions)
['bathe', 'bthe', 'bhe', 'baathe', 'bathe', 'bahe', 'batathe', 'batthe', 'bathe']
You can do it like this:
First, you need some way to remove a certain element from a list:
def without(lst: list, items: list) -> list:
"""
Returns a list without anything in the items list
"""
new_lst = lst.copy()
for e in lst:
if e in items:
items.remove(e)
new_lst.remove(e)
return new_lst
Then, using that function you can create your new word list.
new_word_list = ["".join(without(list(word), list(letter))) for letter in word]
As showed in your wanted output, you don't want the last result of this, so you can just add [:-1] to it.
new_word_list = ["".join(without(list(word), list(letter))) for letter in word][:-1]
Another way you could do it (without the without function):
new_word_list = [word[:index - 1] + word[index:] for index, _ in enumerate(word)][1:]
The [1:] at the end is because you end up with a weird string at the beginning (because of the way it is written). The weird string is bathbathe (when word is bathe)
I have a list which looks like this:
['G1X0.000Y3.000', 'G2X2.000Y3.000I1.000J2.291', 'G1X2.000Y-0.000', 'G2X0.000Y0.000I-1.000J-2.291']
The formatting is such that if the numeric content after X,Y,I or J are positive there is no + sign but if they are negative then the - sign is included. I am trying to loop through this list and to basically add the + sign if there is no - sign at the start of the numeric content. The result should look like this:
['G1X+0.000Y+3.000', 'G2X+2.000Y+3.000I+1.000J+2.291', 'G1X+2.000Y-0.000', 'G2X+0.000Y+0.000I-1.000J-2.291']
I'm trying to use a list comprehension to do so as follows:
#Make sure that X, Y, I and J start with + or -
for count,i in enumerate(fileContents):
if 'G' in i:
indexOfI = i.index("X")
if(i[indexOfI+1]!="-"):
print(i[:indexOfI+1] + "+" + i[indexOfI+1:])
fileContents[count] = i[:indexOfI+1] + "+" + i[indexOfI+1:]
indexOfY = i.index("Y")
if(i[indexOfY+1]!="-"):
fileContents[count] = i[:indexOfY+1] + "+" + i[indexOfY+1:]
if "G2" in i:
indexOfI = i.index("I")
if(i[indexOfI+1]!="-"):
fileContents[count] = i[:indexOfI+1] + "+" + i[indexOfI+1:]
indexOfJ = i.index("J")
if(i[indexOfJ+1]!="-"):
fileContents[count] = i[:indexOfJ+1] + "+" + i[indexOfJ+1:]
the statement print(i[:indexOfI+1] + "+" + i[indexOfI+1:]) gives an output in the console of:
G1X+0.000Y3.000
G2X+2.000Y3.000I1.000J2.291
G1X+2.000Y-0.000
G2X+0.000Y0.000I-1.000J-2.291
Which shows me that this performs what I want it to, however if I print fileContents after this function there are no changes to the list. In other words the following line of code does not replace the list item in each position as I expect it to:
fileContents[count] = i[:indexOfI+1] + "+" + i[indexOfI+1:]
Why does this not work when I can do the following and it does update the list correctly?
#Format each command to a 32 byte string
for i, s in enumerate(fileContents):
fileContents[i] =s.ljust(32,'#')
edit: I originally titled the post "Why doesn't using a list comprehension this way replace each item in the list?". Users have kindly pointed out this has nothing to do with a list comprehension. I apologise, I thought this format x in list was a list comprehension.
if I print fileContents after this function there are no changes to the list.
Actually, there are changes, but at most one + is added (the last one).
This is because you don't apply the same change to i, which means that the next if blocks will copy a part from i back to fileContents[count] that didn't have the previous change.
The quick fix is to make sure you apply the change also to i. Something like:
fileContents[count] = i = i[:indexOfI+1] + "+" + i[indexOfI+1:]
# ^^^^
You can perform this task with list comprehension using re.sub:
import re
fileContents = [re.sub(r"([XYIJ])(?=\d)", r"\1+", line) for line in fileContents]
This will match any X, Y, I or J followed by a digit. In that case, a plus is inserted between those. If you need more strict matching rules, where the line must start with "G", ...etc, then the regular expression will become more complex.
In the loop
for i, s in enumerate(fileContents):
you iterate over the fileContents list, which you want to change in the same loop. It's always dangerous.
Iterate over a copy of this list, which you may simply create by adding [:] to it:
for i, s in enumerate(fileContents[:]):
You can just add + after any of these chars, then replace back +- (f any) with -:
def my_replace(item):
for char in 'XYIJ':
item = item.replace(char, f'{char}+')
return item.replace('+-', '-')
spam = ['G1X0.000Y3.000', 'G2X2.000Y3.000I1.000J2.291',
'G1X2.000Y-0.000', 'G2X0.000Y0.000I-1.000J-2.291']
eggs = [my_replace(item) for item in spam] # now, this is list comprehension
print(eggs)
output
['G1X+0.000Y+3.000', 'G2X+2.000Y+3.000I+1.000J+2.291', 'G1X+2.000Y-0.000', 'G2X+0.000Y+0.000I-1.000J-2.291']
I'm trying to generate a list of combinations from a list of strings with a common separator without reverse duplicates using the code below:
separator = "*";
VarList = ["y","lp","ep","rmp","cmp","cp","fp"]
newVarList = [];
currPosition = 0
for currVar in VarList:
currPosition +=1
nextPosition = 0
for nextVar in VarList:
nextPosition+=1
if currPosition != nextPosition:
currText = currVar + separator + nextVar
if currText not in newVarList:
newVarList.append(currText)
print len(newVarList)
print(' '.join(map(str, newVarList)))
I've managed to generate the combinations and have them listed without brackets or quotes but the reverse duplicates still exist. Any advice would be greatly appreciated.
Make sure currPosition is always smaller than nextPosition:
Maybe by changing
if currPosition != nextPosition:
to
if currPosition < nextPosition:
That should remove the duplicates.
For example, where:
list = [admin, add, swear]
st = 'siteadmin'
st contains string admin from list.
How can I perform this check?
How can I be informed which string from list was found, and if possible where (from start to finish in order to highlight the offending string)?
This would be useful for a blacklist.
list = ['admin', 'add', 'swear']
st = 'siteadmin'
if any([x in st for x in list]):print "found"
else: print "not found"
You can use any built-in function to check if any string in the list appeared in the target string
You can do this by using list-comprehessions
ls = [item for item in lst if item in st]
UPD:
You wanted also to know position :
ls = [(item,st.find(item)) for item in lst if st.find(item)!=-1]
Result :
[('admin', 4)
You can find more information about List Comprehensions on this page
I am assuming the list is very large. So in this program, I am keeping the matched items in a list.
#declaring a list for storing the matched items
matched_items = []
#This loop will iterate over the list
for item in list:
#This will check for the substring match
if item in st:
matched_items.append(item)
#You can use this list for the further logic
#I am just printing here
print "===Matched items==="
for item in matched_items:
print item
Is this what you are looking for?
for item in list:
if item in st:
print(item)
break
else:
print("No string in list was matched")
for x in list:
loc = st.find(x)
if (loc != -1):
print x
print loc
string.find(i) returns the index of where the substr i begins in st, or -1 on failure. This is the most intuitive answer in my opinion, you can make this probably into a 1 liner, but I'm not a big fan of those usually.
This gives the extra value of knowing where the substring is found in the string.
I would like to take a list of strings which represent individual lines entered in a CLI and put '~$ ' at the beginning so when I display them it is more clear that they are command lines. I tried this
command = # a multiline block of command lines
lines = command.split('\n')
for l in lines:
l = '~$ ' + l
for l in lines: print l
But this modifies the temporary variable l I think without going back and changing the actual value in the list. If I put the print inside of the first loop it prints with the correct values, but if I do it like shown the change isn't made. Thanks in advance for any help.
Use a list comprehension:
lines = ['~$ ' + line for line in command.split('\n')]
If you have to use a for loop, you'd use enumerate() to include an index so you can replace the individual items in the list:
for i, line in enumerate(lines):
lines[i] = '~$ ' + line
The functional way:
list(map(lambda s: '~$ ' + s, command.splitlines()))