What do these single quotes do at the beginning of line 2? - python

I found the following code in some random website explaining concatenating:
data_numb = input("Input Data, then press enter: ")
numb = ''.join(list(filter(str.isdigit, data_numb)))
print('(' + numb[:3] + ') ' + numb[3:6] + '-' + numb[6:])
and I was wondering what the single quotes do in the
numb = ''.join(
Any help is appreciated!

join(iterable) is a method from the str class.
Return a string which is the concatenation of the strings in iterable.
A TypeError will be raised if there are any non-string values in
iterable, including bytes objects. The separator between elements is
the string providing this method.
''.join(("Hello", "World")) will return 'HelloWorld'.
';'.join(("Hello", "World", "how", "are", "you")) will return 'Hello;World;how;are;you'.
join is very helpful if you need to add a delimiter between each element from a list (or any iterable) of strings.
It looks like nothing but if you do not use join, this kind of operation is often ugly to implement because of edge effects:
For a list or tuple of strings :
def join(list_strings, delimiter):
str_result = ''
for e in list_strings[:-1]:
str_result += e + delimiter
if list_strings:
str_result += list_strings[-1]
return str_result
For any iterable :
def join(iterable, delimiter):
iterator = iter(iterable)
str_result = ''
try:
str_result += next(iterator)
while True:
str_result += delimiter + next(iterator)
except StopIteration:
return str_result
Because join works on any iterable, you don't need to create a list from the filter result.
numb = ''.join(filter(str.isdigit, data_numb))
works as well

Join method is used to concatenate a string with any iterable object. In this example, the first string is an empty string, also represented by two single quotes, '' (don't confuse the single quotes with a single double quote).
The join() method of a string object concatenates it with another iterable provided. So, if the first string is an empty string, the resultant string is the concatenated output of the elements in the iterable.
What is its use:
It can be used to concatenate a list of strings. For example:
a = ['foo', 'bar']
b = ''.join(a)
print(b) # foobar
It can be used to concatenate strings. (Since a string is an iterable, as well)
a = "foobar"
b = ''.join(a)
print(b) # foobar
You can think of more use cases, but this is just a gist of it. You can also refer to the documentation here.

Related

Handling spaces differently when converting between lists and strings

I want to be able to convert some strings to lists of characters, and vice versa. However, all spaces within the strings should be represented by an empty string element in the corresponding list. For example:
typed_words = ['T', "y", "p", "e", "", "t", "h", "i", "s"]
target_text = "Type this"
I've tried using the join method to convert the list into a string, but since there is an empty element in the list, it creates a string with no spaces.
How do I allow for the special case of ''/' ' amidst the rest of the characters?
First of all, if one ignores the space-to-empty-string issue, converting a list of characters to a string and back again is as simple as:
# Converting the list to a string:
total_string = ''.join(list_of_characters)
# Converting the string to a list:
list_of_characters = list(total_string)
In your case, you need the extra step of converting between spaces and empty strings, which you can accomplish with a list comprehension.
For instance, here's a list comprehension (split onto multiple lines for extra clarity) that reproduces a list faithfully, except with empty string elements replaced with spaces:
[
' ' if char == '' else char
for char in list_of_characters
]
So your final conversions would look like this:
# Converting the list to a string:
total_string = ''.join([' ' if char == '' else char for char in list_of_characters])
# Converting the string to a list:
list_of_characters = ['' if char == ' ' else char for char in total_string]
Note that one can iterate over a string just like iterating over a list, which is why that final comprehension can simply iterate over total_string rather than having to do list(total_string).
P.S. An empty string ('') evaluates to False in boolean contexts, so you could make use of the or operator's short-circuiting behavior to use this shorter (though arguably less immediately legible) version:
# Converting the list to a string:
total_string = ''.join([char or ' ' for char in list_of_characters])
For making a list, you need to iterate every char and append it to a list.
def strToList(s):
l = []
for c in s:
l.append(c)
return l
For doing the inverse operation, python allows using the += operator on strings:
def listToStr(l):
s = ""
for c in l:
s += str(c)
return s
We can do something as simple as the following, which is the general case
from typing import List # native python pkg, no need to install
def list_to_string(lst: List[str]) -> str:
return " ".join(lst)
def string_to_list(str_: str) -> List[str]:
return str_.split("")
if we want to cater to your needs that if there is an empty string, replace it with space, we shall do the following
def list_to_string(lst: List[str]) -> str:
'''
Here we loop over the characters in a list,
check if character "c" is space, then append it
otherwise replaced with an empty string
#param list: (List) expects a list of strings
#returns String object of characters appended together
'''
return " ".join([c if c not c.isspace() else "" for c in lst])
Why am I following a one-liner approach? This is due to the fact that Pythonic approaches are better IMHO as they are more readable, compact, and neat i.e. Pythonic
Yet we can also implement the solutions using normal for loops, which is the same thing yet I prefer one-liners. And we can use string concatenation but strings are immutable objects, so every time we append to the main string we have created another string, and so on for as lengthy as the given list, which is not an optimal approach due to the increased number of variables created and memory consumption (which in your case might not be that much, but better keep an eye for that)

Python: how do I make a recursive function that returns a string of words in reverse order?

I'm trying to create a recursive function that accepts a string as a parameter and returns the words in that string in reverse. To clarify, if the string was "Today is Sunday", it's supposed to return "Sunday is Today". Here's what I have so far:
def reverse(msg):
new_msg = msg.split()
if len(new_msg)==0:
return new_msg
else:
return str(new_msg[-1])+str(reverse(new_msg[0:-1]))
But once I use a string as a parameter, the console gives me "AttributeError: 'list' object has no attribute 'split'". What can I do to fix this?
Your issue is that your function is mixing lists with strings. Use the join method to convert the list you created with split back to a string.
Update your function to:
def reverse(msg):
new_msg = msg.split()
if len(new_msg) <= 1:
return msg
else:
return new_msg[-1] + " " + reverse(" ".join(new_msg[0:-1]))
If you're going to use string indexing, particularly negative indexes, then there's no point to using recursion:
def reverse(msg):
return " ".join(msg.split()[-1::-1])
Let's eliminate the indexes and use the maxsplit argument to split() to keep from doing work that we might otherwise just throw away again with a join():
def reverse(message):
if not message:
return message
first, *rest = message.split(maxsplit=1)
if not rest:
return first
return reverse(*rest) + ' ' + first
print(reverse("get your facts first then you can distort them as you please"))

How to replace multiple matches in Regex

I'm trying to replace '=' with '==' in the following string:
log="[x] = '1' and [y] <> '7' or [z]='51'".
Unfortunately, only the second '=' is getting replaced. Why is the first one not being replaced and how do I replace the first one as well?
def subs_equal_sign(logic):
y = re.compile(r'\]\s?\=\s?')
iterator = y.finditer(logic)
for match in iterator:
j = str(match.group())
return logic.replace(j, ']==')
The output should be:
log="[x] == '1' and [y] <> '7' or [z]=='51'".
This is what i get instead:
log="[x] = '1' and [y] <> '7' or [z]=='51'".
for match in iterator:
j = str(match.group())
return logic.replace(j, ']==')
This part goes through the matches and doesn't do any replacing.
Only when you leave the loop, you do replacing - that's why it changes only the last one. ;)
Also, you do replacing without using the regex - simple str.replace takes all substrings matches and replaces them. So if your first = didn't have space before, it would get changed anyway!
Looking at your regex, there is only one space possible between ] and =, so why not do the replacing on those two cases, instead of using regexes? ;)
def subs_equal_sign(logic):
return logic.replace(']=', ']==').replace('] =', ']==')
Maybe the replace() function is what you are looking for :
log="[x] = '1' and [y] <> '7' or [z]='51'"
log = log.replace("=", "==")
Change your function to
def subs_equal_sign(logic):
y = re.compile(r'\]\s?\=\s?')
return y.sub("]==", logic)
and the output will now be
>>> subs_equal_sign('''log="[x] = '1' and [y] <> '7' or [z]='51'".''')
'log="[x]==\'1\' and [y] <> \'7\' or [z]==\'51\'".'
as expected.
#h4z3 correctly pointed out that your key problem is iterating through the matched groups without doing anything to them. You can make it work by simply using re.sub() to replace all occurrences at once.
A quick way to deal with this is to remove the whitespace:
def subs_equal_sign(logic):
for k in range(len(logic))):
logic[k].replace(' ','')
y = re.compile(r'\]\s?\=\s?')
iterator = y.finditer(logic)
for match in iterator:
j = str(match.group())
return logic.replace(j, ']==')
Does the string represent the branching logic for a REDCap variable? If so, I wrote a function a while back that should convert REDCap's SQL-like syntax to a pythonic form. Here it is:
def make_pythonic(str):
"""
Takes the branching logic string of a field name
and converts the syntax to that of Python.
"""
# make list of all checkbox vars in branching_logic string
# NOTE: items in list have the same serialization (ordering)
# as in the string.
checkbox_snoop = re.findall('[a-z0-9_]*\([0-9]*\)', str)
# if there are entries in checkbox_snoop
if len(checkbox_snoop) > 0:
# serially replace "[mycheckboxvar(888)]" syntax of each
# checkbox var in the logic string with the appropraite
# "record['mycheckboxvar___888']" syntax
for item in checkbox_snoop:
item = re.sub('\)', '', item)
item = re.sub('\(', '___', item)
str = re.sub('[a-z0-9_]*\([0-9]*\)', item, str)
# mask and substitute
str = re.sub('<=', 'Z11Z', str)
str = re.sub('>=', 'X11X', str)
str = re.sub('=', '==', str)
str = re.sub('Z11Z', '<=', str)
str = re.sub('X11X', '>=', str)
str = re.sub('<>', '!=', str)
str = re.sub('\[', 'record[\'', str)
str = re.sub('\]', '\']', str)
# return the string
return str
This could replace the given character with the new char to be replaced in the entire string.
log=log.replace("=","==")#Replaces the given substring with new string
print(log)#Display

Converting uppercase to lowercase with hyphen

I'm processing some CSS code using Python, since they came from a JSON file (JSON doesn't accept hyphens) they have a particular notation eg.. font-size = fontSize, I'd like to convert every uppercases letter and put them back in the right CSS format inserting a hyphen right before the uppercase.
string = 'borderRadius: 0px, zIndex: 2, transform: translate(170px, 195px) skew(-30deg, 0deg), fontSize:30px'
def getIndices(string):
// get position of each capital letters.
index = [i for i, c in enumerate(string) if c.isupper()]
// code below would be inserted here.
// insert hyphen right before the upperscase
for i in index:
string = string[:i] + '-' + string[i:]
// once done, set string to lowercase since there are no uppercases in CSS properties
string = string.lower()
return string
getIndices(string)
The issue is that each time a hyphen is insered, the position of capital letters becomes off hence the insertion are off too.
I thought about enumarting the index and increasing each int in list by their index number, but I'm probably doing something not quite right.
...
index = [25, 35, 58]
for i, value in enumerate(index):
value = value + (i)
index[i] = value
Any suggestion would be helpful!
If I got it right, this is one way of doing it
for c in my_string:
print c
if c.isupper():
my_string = my_string.replace(c,"-%s" % c.lower())
print my_string # will print fontSize = font-size
You could simply do your insertions in reverse. Otherwise the first ones will change the offset of the last ones. This can be done by calling reversed on the index list before looping over it.
def getIndices(string):
# get position of each capital letters.
index = [i for i, c in enumerate(string) if c.isupper()]
# code below would be inserted here.
# insert hyphen right before the upperscase
for i in reversed(index):
string = string[:i] + '-' + string[i:]
# once done, set string to lowercase since there are no uppercases in CSS properties
string = string.lower()
return string
But it would be better to avoid:
string = string[:i] + '-' + string[i:]
As it makes four new strings every loop iteration.
By building a list and then calling '-'.join. The following works:
def getIndices(string):
# get position of each capital letters.
index = [i for i, c in enumerate(string) if c.isupper()]
# code below would be inserted here.
# insert hyphen right before the upperscase
l = []
e = len(string)
for i in reversed(index):
l.append(string[i:e])
e = i
l.append(string[:e])
l.reverse()
string = '-'.join(l)
# once done, set string to lowercase since there are no uppercases in CSS properties
string = string.lower()
return string
I'd like to do:
l = []
e = len(string)
for i, c in reversed(enumerate(string)):
if c.isupper():
l.append(string[i:e])
e = i
l.append(string[:e])
l.reverse()
string = '-'.join(l)
[The code above does not work as it results in TypeError: argument to reversed() must be a sequence but the error is misleading the argument must either be a sequence or an object that has __reversed__ defined]
But when they added reversed they didn't think about making it applicable to all built-in iterator functions by defining __reversed__ that returns the reverse they are iterating over an iterable that has a __reversed__. I've implemented an enumerate that works that way and find it Pythonic. Oddly it works on xrange but not on enumerate so the code becomes:
def getIndices(string):
l = []
e = len(string)
for i in reversed(xrange(len(string))):
if string[i].isupper():
l.append(string[i:e])
e = i
l.append(string[:e])
l.reverse()
string = '-'.join(l)
string = string.lower()
return string

How to convert single element tuple into string?

I have this code:
import nltk
import pypyodbc
text = raw_input()
token = nltk.word_tokenize(text) //return a list value
def search(self, lists):
if not self.connected:
self.connect()
for word in lists:
self.cur.execute('SELECT Ybanag FROM Words WHERE English IN (%s)' % (','.join('?'*len(lists))), lists)
result = self.cur.fetchall()
return result
wherein the output is a list of single element tuple (ex. I enter we all there):
[('tore',), ('ngaming',), ('sittam',)] (translate the input into mother tongue language). I want that the output will be converted into string to eliminate the [],(),'',' symbols. How to convert it into string?
You have to use str.join method.
>>> a = [('tore',), ('ngaming',), ('sittam',)]
>>> " ".join([x[0] for x in a])
'tore ngaming sittam'
I would just use a for loop. You can loop through the list of tuples and add each element to an empty string variable
x = [('tore'), ('ngaming'), ('sittam')]
z = ""
for i in x:
z = z + i + " "
print z
After seeing Lafada's answer, I realized that list comprehension and str.join is the best option. Though his answer is better, this is basically what his answer does, just done more manually.

Categories

Resources