How to print string tuple without commas - python

I'm new to Python, If i have this tuple
testGrid = [['p','c','n','d','t','h','g'],
['w','a','x','o','a','x','f'],
['o','t','w','g','d','r','k'],
['l','j','p','i','b','e','t'],
['f','v','l','t','o','w','n']]
How can I print it out so that it reads without any commas and without spaces? And new lines after each row?
pcndthg
waxoaxf
otwgdrk
ljpibet
fvltown

Use join() to concatenate all the strings in a list.
for row in testGrid:
print(''.join(row))
or change the default separator to an empty string.
for row in testGrid:
print(*row, sep='')

Barmar's answer is likely the most efficient possible way to do this in Python, but for the sake of learning programming logic, here is an answer that guides you through the process step by step:
First of all, in a nested list, usually 2 layers of loops are required (if no helper or built-in functions are used). Hence our first layer of for loop will have a 1D list as an element.
for row in testGrid:
print("something")
# row = ['p','c','n','d','t','h','g']
So within this loop, we attempt to loop through each alphabet in row:
for char in row:
print(char)
# char = 'p'
Since the built-in print() function in Python will move to the next line by default, we try to use a string variable to "stack" all characters before outputting it:
for row in testGrid:
# loop content applies to each row
# define string variable
vocab = ""
for char in row:
# string concatenation (piecing 2 strings together)
vocab = vocab + char
# vocab now contains the entire row, pieced into one string
print(vocab)
# remark: usually in other programming languages, moving cursor to the next line requires extra coding
# in Python it is not required but it is still recommended to keep this in mind
Hopefully this helps you understand programming concepts and flows better!

Related

Moving for loop into a reduce method

I am trying to plot the location of ~4k postcodes onto a UK map, I am using a library that can take in the postcode and kick back latitude, longitude etc.., however the postcode must always contain a space before the last 3 characters in the string, for example:
'AF23 4FR' would be viable as the space is before the last 3 chars in the string..
'AF234FR' would not be allowed as there is no space..
I have to go over each item within my list and check there is a space before the n-3 position in the string, I can do this with a simple for loop but I would prefer to do this with a reduce function. I am struggling to workout how I would rework the check and logic of the following into a reduce method, would it even be worth it in this scenario:
for index, p in enumerate(data_set):
if (p.find(' ') == -1):
first = p[:len(p)]
second = p[len(first):]
data_set[index] = first + ' ' + second
You're pretty much there... Create a generator with spaces removed from your string, then apply slicing and formatting, and use a list-comp to generate a new list of foramtted values, eg:
pcs_without_spaces = (pc.replace(' ', '') for pc in data_set)
formatted = ['{} {}'.format(pc[:-3], pc[-3:]) for pc in pcs_without_spaces)
That way, you don't need additional logic on whether it's got a space or not already in it, as long as your postcode is going to be valid after slicing, just removing the spaces and treating everything with the same logic is enough.

How to iterate through a list and use .isdigit to verify if a list of strings is made up of only digits or not

Write a function that takes, as an argument, a list, identified by the variable aList. If the list only contains elements containing digits (either as strings as integers), return the string formed by concatenating all of the elements in the list (see the example that follows). Otherwise, return a string indicating the length of the list, as specified in the examples that follow.
I am just starting to learn how to code and this is my first CS class.
def amIDigits(aList):
for element in range(aList):
if element in aList.isdigit():
bList=[]
bList.append(aList)
return str(bList)
amIDigits([“hello”, 23]) should return the string “The length of the input is 2.”
amIDigits ([“10”, “111”]) should return the string “10111”
If I understand it right the output will be the joined digits even if they are not of the string format. So the best way is to use the all function (returns true if all elements of an iteration are true) and check if the string elements of the list are digits. If so, then return the join of all elements of the list converted to a string. Else, we return the length of the list using the new string formatting syntax (f represents string formatting and the {} return the result of an operation).
code:
def amIDigits(aList):
if all([str(i).isdigit() for i in aList]):
return ''.join(map(str,aList))
else:
return f'The length of the input is {len(aList)}.'
print(amIDigits(['hello', 23]))
print(amIDigits(['10', '111']))
print(amIDigits([55, 33]))
output:
The length of the input is 2.
10111
5533
First, I highly recommend having someone literally sit down and have you walk them through your thought process. It is more useful as a learner to debug your thought process than to have someone give you the answer.
One thing I noticed is that you created your empty list, bList, inside the for block. This will not work. You need to create an empty list to store things into before you begin for looping through the old list, otherwise you will be over-writing your new list every time it loops. So right now, your bList.append() statement is appending an element onto an empty list every time it runs. (You will get only the very last element in the aList stored into your bList.)
Another problem is that you use the range() function, but you don't need to. You want to look at each element inside the list. Range creates a sequence of numbers from 0 to whatever number is inside the parentheses: range() documentation. Your code tries to pass a list into range(), so it is invalid.
The "for blank in blank" statement breaks up whatever list is in the second blank and goes through each of its elements one at a time. For the duration of the for statement, the first blank is the name of the variable that refers to the element being looked at. so for example:
apples = ["Granny Smith","Red Delicious","Green"]
for apple in apples:
eat(apple) #yum!
The for in statement is more naturally spoken as "for each blank in blank:"

Swapping pairs of characters in a string

Okay, I'm really new to Python and have no idea how to do this:
I need to take a string, say 'ABAB__AB', convert it to a list, and then take the leading index of the pair I want to move and swap that pair with the __. I think the output should look something like this:
move_chars('ABAB__AB', 0)
'__ABABAB'
and another example:
move_chars('__ABABAB', 3)
'BAA__BAB'
Honestly have no idea how to do it.
Python strings are immutable, so you can't really modify a string. Instead, you make a new string.
If you want to be able to modify individual characters in a string, you can convert it to a list of characters, work on it, then join the list back into a string.
chars = list(str)
# work on the list of characters
# for example swap first two
chars[0], chars[1] = chars[1], chars[0]
return ''.join(chars)
I think this should go to the comment section, but I can't comment because of lack of reputation, so...
You'll probably want to stick with list index swapping, rather than using .pop() and .append(). .pop() can remove elements from arbitrary index, but only one at once, and .append() can only add to the end of the list. So they're quite limited, and it would complicate your code to use them in this kind of problems.
So, well, better stick with swapping with index.
The trick is to use list slicing to move parts of the string.
def move_chars(s, index):
to_index = s.find('__') # index of destination underscores
chars = list(s) # make mutable list
to_move = chars[index:index+2] # grab chars to move
chars[index:index+2] = '__' # replace with underscores
chars[to_index:to_index+2] = to_move # replace underscores with chars
return ''.join(chars) # stitch it all back together
print(move_chars('ABAB__AB', 0))
print(move_chars('__ABABAB', 3))

using replace method in a loop in python

Consider a text file and 2 lists. In list_A there are some letters and in list_B some other letters. I want an algorithm to find the letters in the text which exist in list_A, and replaces them with letters with the same index from list_B. It finds and replaces them, but, each time it replaces it the previous result disappears.
I mean at last, I have the result of the last replacement in the print. How can I solve this problem? I mean I want a print in which all the letters are replaced, not just the last one.
what could be the problem with this loop:
for i in text:
if i in list_A:
p=text.replace(i, list_B[list_A.index(i)])
print(p)
With this line:
p=text.replace(i, list_B[list_A.index(i)])
Each time through the loop you're taking text and assigning a new version of it to p, but you're never updating text to contain the new copy (Which you probably shouldn't do, as you're iterating over it).
I'd start by making p a copy of text outside the loop, and inside, doing p = p.replace(...
Bear in mind that with the method you've chosen, you also have to worry about multiple replacements and the order in which you're checking. For example, if you are replacing all a with b, and also wanting to replace all b with c, then using your method if you start with aaaa you will end up with cccc (because it replaces them all with b, then checks for b...) , when you might have only wanted to replace the a if it was in the original string. If you're worried about that, I'd look at maketrans and translate as mentioned by bereal in a comment.
This should work.
temp = text
for i in temp:
if i in list_A:
temp=temp.replace(i, list_B[list_A.index(i)])
print "Original:",text
print "Modified: ",temp

Any way to split python string without generate new strings?

The input is a string containing a huge number of characters, and I hope to split this string into a list of strings with a special delimiter.
But I guess that simply using split would generate new strings rather than split the original input string itself, and in that case it consumes large memory(it's guaranteed that the original string would not be used any longer).
So is there a convenient way to do this destructive split?
Here is the case:
input_string = 'data1 data2 <...> dataN'
output_list = ['data1', 'data2', <...> 'dataN']
What I hope is that the data1 in output_list is and the data1(and all others) in input_string shares the same memory area.
BTW, for each input string, the size is 10MB-20MB; but as there are lots of such strings(about 100), so I guess memory consumption should be taken into consideration here?
In Python, strings are immutable. This means that any operation that changes the string will create a new string. If you are worried about memory (although this shouldn't be much of an issue unless you are dealing with gigantic strings), you can always overwrite the old string with the new, modified string, replacing it.
The situation you are describing is a little different though, because the input to split is a string and the output is a list of strings. They are different types. In this case, I would just create a new variable containing the output of split and then set the old string (that was the input to the split function) to None, since you guarantee it will not be used again.
Code:
split_str = input_string.split(delim)
input_string = None
The only alternative would be to access the substrings using slicing instead of split. You can use str.find to find the position of each delimiter. However this would be slow, and fiddly. If you can use split and get the original string to drop out of scope then it would be worth the effort.
You say that this string is input, so you might like to consider reading a smaller number of characters so you are dealing with more manageable chunks. Do you really need all the data in memory at the same time?
Perhaps the Pythonic way would be to use iterators? That way, the new substrings will be in memory only one at a time. Based on
Splitting a string into an iterator :
import re
string_long = "my_string " * 100000000 # takes some memory
# strings_split = string_long.split() # takes too much memory
strings_reiter = re.finditer("(\S*)\s*", string_long) # takes no memory
for match in strings_reiter:
print match.group()
This works fine without leading to memory problems.
If you're talking about strings that are SO huge that you can't stand to put them in memory, then maybe running through the string once (O(n), probably improvable using str.find but I'm not sure) then storing a generator that holds slice objects would be more memory-efficient?
long_string = "abc,def,ghi,jkl,mno,pqr" # ad nauseum
splitters = [','] # add whatever you want to split by
marks = [i for i,ch in enumerate(long_string) if ch in splitters]
slices = []
start = 0
for end in marks:
slices.append(slice(start,end))
start = end+1
else:
slices.append(slice(start,None))
split_string = (long_string[slice_] for slice_ in slices)

Categories

Resources