Python not ignoring empty items in list - python

I have this code to print some strings to a text file, but I need python to ignore every empty items, so it doesn't print empty lines.
I wrote this code, which is simple, but should do the trick:
lastReadCategories = open('c:/digitalLibrary/' + connectedUser + '/lastReadCategories.txt', 'w')
for category in lastReadCategoriesList:
if category.split(",")[0] is not "" and category is not None:
lastReadCategories.write(category + '\n')
print(category)
else: print("/" + category + "/")
lastReadCategories.close()
I can see no problem with it, yet, python keeps printing the empty items to the file. All categories are written in this notation: "category,timesRead", that's why I ask python to see if the first string before the comma is not empty. Then I see if the whole item is not empty (is not None). In theory I guess it should work, right?
P.S.: I've already tried asking the if to check if 'category' is not "" and is not " ", still, the same result.

Test for boolean truth instead, and reverse your test so that you are certain that .split() will work in the first place, None.split() would throw an exception:
if category is not None and category.split(",")[0]:
The empty string is 'false-y', there is no need to test it against anything.
You could even just test for:
if category and not category.startswith(','):
for the same end result.
From comments, it appears you have newlines cluttering up your data. Strip those away when testing:
for category in lastReadCategoriesList:
category = category.rstrip('\n')
if category and not category.startswith(','):
    lastReadCategories.write(category + '\n')
    print(category)
else: print("/{}/".format(category))
Note that you can simply alter category inside the loop; this avoids having to call .rstrip() multiple times.

rstrip() your category before writing it back to file
lastReadCategories = open('c:/digitalLibrary/' + connectedUser +'/lastReadCategories.txt', 'w')
for category in lastReadCategoriesList:
if category.split(",")[0] is not "" and category is not None:
lastReadCategories.write(category.rstrip() + '\n')
print(category.rstrip())
else: print("/" + category + "/")
lastReadCategories.close()
I was able to test it with your sample list provided (without writing it to file):
lastReadCategoriesList = ['A,52', 'B,1\n', 'C,50', ',3']
for category in lastReadCategoriesList:
if category.split(",")[0] is not "" and category is not None:
print(category.rstrip())
else: print("/" + category + "/")
>>> ================================ RESTART ================================
>>>
A,52
B,1
C,50
/,3/
>>>

The classic way to test for an empty string (ie, only whitespace but not '') is with str.strip():
>>> st=' '
>>> bool(st)
True
>>> bool(st.strip())
False
Which also works on a null string:
>>> bool(''.strip())
False
You have if category.split(",")[0] is not "" ... and this is not the recommended way. You can do this:
if category.split(',')[0] and ...
Or, if you want to be wordier:
if bool(category.split(',')[0]) is not False and ...
And you may be dealing with an issue with leading whitespace in the CSV:
>>> ' ,'.split(',')
[' ', '']
>>> ' ,val'.split(',')
[' ', 'val']

Related

Python - Need help in printing "with at least 3 spaces between columns and be left-aligned for names and right-aligned for number of occurrence."

I am having a problem with this problem in trying to output with at least 3 spaces between columns and be left-aligned for names and right-aligned for number of occurrence. Please guide me, I am trying to solve this programming problem.
def nameCount(fname1,fname2):
firstFile = open(fname1, 'r')
fContent = firstFile.read()
firstFile.close()
secondFile = open(fname2, 'r')
sContent = secondFile.read()
secondFile.close()
#Split first and last name to the following variables.
for content in fContent:
(first, last) = sContent.split()
countFirstName = 0
countSecondName = 0
if first == content or last == content:
countFirstName += 1
countSecondName += 1
thankYouMessage = 'Thank you for using the nameCount() function'
return thankYouMessage
To print with spaces in between test just us the "\n" which goes to a new line.
print("Hello" + "\n" + "\n" + "\n" + "\n" + "World")
Each "\n" makes it go to a newline each time.
You can try using the %s character for formatting columns

Removing Single Quotes from a String Stored in an Array

I wrote code to append a json response into a list for some API work I am doing, but it stores the single quotes around the alphanumerical value I desire. I would like to get rid of the single quotes. Here is what I have so far:
i = 0
deviceID = []
while i < deviceCount:
deviceID.append(devicesRanOn['resources'][i])
deviceID[i] = re.sub('[\W_]', '', deviceID[i])
i += 1
if i >= deviceCount:
break
if (deviceCount == 1):
print ('Device ID: ', deviceID)
elif (deviceCount > 1):
print ('Device IDs: ', deviceID)
the desired input should look like this:
input Device IDs:
['14*************************00b29', '58*************************c3df4']
Output:
['14*************************00b29', '58*************************c3df4']
Desired Output:
[14*************************00b29, 58*************************c3df4]
As you can see, I am trying to use RegEx to filter non Alphanumeric and replace those with nothing. It is not giving me an error nor is it preforming the actions I am looking for. Does anyone have a recommendation on how to fix this?
Thank you,
xOm3ga
You won't be able to use the default print. You'll need to use your own means of making a representation for the list. But this is easy with string formatting.
'[' + ', '.join(f'{id!s}' for id in ids) + ']'
The f'{id:!s} is an f-string which formats the variable id using it's __str__ method. If you're on a version pre-3.6 which doesn't use f-strings, you can also use
'%s' % id
'{!s}'.format(id)
PS:
You can simplify you're code significantly by using a list comprehension and custom formatting instead of regexes.
ids = [device for device in devicesRanOn['resources'][:deviceCount]]
if deviceCount == 1:
label = 'Device ID:'
elif deviceCount > 1:
label = 'Device IDs:'
print(label, '[' + ', '.join(f'{id!s}' for id in ids) + ']')

Passing Text around defs

I want to pass the text that comes from this list to see what is contained in it.
The def used is this:
def getTotal(self) :
total = []
for i in range(self.List.getItemCount()) :
total.append(self.List.getItemText(i))
return total
In my main I have this:
msg+=self.getTotal()
What's the correct way of adding to msg so it'll print correctly to the screen?
Expected output:
['Object1', 'Object2']
I'm assuming you're trying to add the list to a string message. In that case you need to use str() to convert the list into a string:
msg += str(self.getTotal())
You can print the objects in the list by doing:
msg += ', '.join(self.getTotal())
I'm not entirely sure what you expect the output to be but would
output_str = ', '.join(self.getTotal())
assumed the list contains numbers I would do it like this:
print msg + ' ' + str(self.getTotal())
If you want to save the whole content in the message first:
msg += ' ' + str(self.getTotal())
print msg

How to remove newlines and indents from a string in Python?

In my Python script, I have a SQL statement that goes on forever like so:
query = """
SELECT * FROM
many_many
tables
WHERE
this = that,
a_bunch_of = other_conditions
"""
What's the best way to get this to read like a single line? I tried this:
def formattedQuery(query):
lines = query.split('\n')
for line in lines:
line = line.lstrip()
line = line.rstrip()
return ' '.join(lines)
and it did remove newlines but not spaces from the indents. Please help!
You could do this:
query = " ".join(query.split())
but it will not work very well if your SQL queries contain strings with spaces or tabs (for example select * from users where name = 'Jura X'). This is a problem of other solutions which use string.replace or regular expressions. So your approach is not too bad, but your code needs to be fixed.
What is actually wrong with your function - you return the original, the return values of lsplit and rsplit are abandoned. You could fix it like this:
def formattedQuery(query):
lines = query.split('\n')
r = []
for line in lines:
line = line.lstrip()
line = line.rstrip()
r.append(line)
return ' '.join(r)
Another way of doing it:
def formattedQuery(q): return " ".join([s.strip() for s in q.splitlines()])
Another one line:
>>> import re
>>> re.sub(r'\s', ' ', query)
'SELECT * FROM many_many tables WHERE this = that, a_bunch_of = other_conditions'
This replaces all white spaces characters in the string query by a single ' ' white space.
string.translate can remove characters (just provide None for the second argument so it doesn't also convert characters):
import string
string.translate(query, None, "\n\t")

Python RegEx Woes

I'm not sure why this isn't working:
import re
import csv
def check(q, s):
match = re.search(r'%s' % q, s, re.IGNORECASE)
if match:
return True
else:
return False
tstr = []
# test strings
tstr.append('testthisisnotworking')
tstr.append('This is a TEsT')
tstr.append('This is a TEST mon!')
f = open('testwords.txt', 'rU')
reader = csv.reader(f)
for type, term, exp in reader:
for i in range(2):
if check(exp, tstr[i]):
print exp + " hit on " + tstr[i]
else:
print exp + " did NOT hit on " + tstr[i]
f.close()
testwords.txt contains this line:
blah, blah, test
So essentially 'test' is the RegEx pattern. Nothing complex, just a simple word. Here's the output:
test did NOT hit on testthisisnotworking
test hit on This is a TEsT
test hit on This is a TEST mon!
Why does it NOT hit on the first string? I also tried \s*test\s* with no luck. Help?
The csv module by default returns blank spaces around words in the input (this can be changed by using a different "dialect"). So exp contains " test" with a leading space.
A quick way to fix this would be to add:
exp = exp.strip()
after you read from the CSV file.
Adding a print repr(exp) to the top of the first for loop shows that exp is ' test', note the leading space.
This isn't that surprising since csv.reader() splits on commas, try changing your code to the following:
for type, term, exp in reader:
exp = exp.strip()
for s in tstr:
if check(exp, s):
print exp + " hit on " + s
else:
print exp + " did NOT hit on " + s
Note that in addition to the strip() call which will remove the leading a trailing whitespace, I change your second for loop to just loop directly over the strings in tstr instead of over a range. There was actually a bug in your current code because tstr contained three values but you only checked the first two because for i in range(2) will only give you i=0 and i=1.

Categories