Replace dashes with whitespaces for all elements across a tuple? - python

I'm building off of these two questions because they don't quite answer my question:
How to change values in a tuple?
Python: Replace "-" with whitespace
If I have a tuple like this:
worldstuff = [('Hi', 'Hello-World', 'Earth'), ('Hello-World', 'Hi'), ...]
How do I replace dashes with whitespaces for all of the elements across all lists in a tuple? The previous Stack Overflow question covers changing the specific index of one list in a tuple, but not if there are multiple occurances of an element needing to be replaced.
I've tried doing the following, which doesn't quite work:
worldstuff_new = [x.replace('-', ' ') for x in worldstuff]
But if I do it for a specific list in the tuple, it works for that tuple list. I'm trying to avoid having to do separate lists and instead trying to do it all at once.
worldstuff_new = [x.replace('-', ' ') for x in worldstuff[0]]
I understand that tuples are immutable, which is why I am having trouble figuring this out. Is this possible? Would appreciate any help - thanks.

Correct expression:
a = [('Hi', 'Hello-World', 'Earth'), ('Hello-World', 'Hi')]
b = [tuple([x.replace('-', ' ') for x in tup]) for tup in a]
>>> b
[('Hi', 'Hello World', 'Earth'), ('Hello World', 'Hi')]
A few notes:
Please don't clobber builtins (tuple).
What you have is actually not a tuple, but a list of tuples.
As you note, tuples are immutable; but you can always build new tuples from the original ones.
(Speed) Why tuple([x.replace ...]) (tuple of a list comprehension) instead of tuple(x.replace ...) (tuple of the output of a generator)? Because the former is slightly faster.

first of everything, don't name any variable tuple it's a builtin function and when you name a variable tuple you miss that method
def changer(data):
if type(data) == str:
return data.replace("-", " ")
elif type(data) == list:
return [changer(x) for x in data]
elif type(data) == tuple:
return tuple(changer(x) for x in data)
tpl = [('Hi', 'Hello-World', 'Earth'), ('Hello-World', 'Hi')]
changer(tpl)
output:
[('Hi', 'Hello World', 'Earth'), ('Hello World', 'Hi')]

tuple_old = [('Hi', 'Hello-World', 'Earth'), ('Hello-World', 'Hi')]
tuple_new = [
tuple([x.replace('-', ' ') for x in tup]) for tup in tuple_old
]
print(tuple_new)
FWIW, tuples are the things in parentheses. Lists are in square brackets. So you have a list of tuples, not a tuple of lists.

There are a few things that might help you to understand:
You cannot change a tuple or a string. you can only create a new one with different contents.
All the functions that "modify" a string are actually just creating a new string that has been modified from the original. Your original question that you referenced also slightly mis-understood one of the quirks of python where you can iterate over the characters in a string, but due to python not having a character datatype, they just end up as new strings. tldr; replacing "-" with " " looks just like this:
print("old-str".replace("-", " "))
This will generate a new string with all the dashes replaced.
Now you need to extend this to creating a new tuple of strings. You can create a new tuple with the built-in-function (which you had previously accidentally overwrote with a variable) tuple and passing in some sort of iterable. In this case I will use a generator expression (similar to list comprehension but without the square brackets) to create this iterable:
tuple(entry.replace("-", " ") for entry in old_tup)
finally you can apply this to each tuple in your list either by creating a new list, or by over-writing the values in the existing list (example shows creating a new list with a list comprehension):
[tuple(entry.replace("-", " ") for entry in old_tup) for old_tup in worldstuff ]

This might help:
worldstuff_new = [tuple(x.replace('-', ' ') for x in t) for t in worldstuff]

If you want a different way to do this you could use the map function like so.
tuples = [('Hi','Hello-World', 'Earth'), ('Hello-World', 'Hi'), ('Te-st', 'Te-st2')]
new_tuples = list(map(lambda tup: tuple(item.replace('-', ' ') for item in tup), tuples))
output:
[('Hi', 'Hello World', 'Earth'), ('Hello World', 'Hi'), ('Te st', 'Te st2')]

Related

Remove all words from a string that exist in a list

community.
I need to write a function that goes through a string and checks if each word exists in a list, if the word exists in the (Remove list) it should remove that word if not leave it alone.
i wrote this:
def remove_make(x):
a = x.split()
for word in a:
if word in remove: # True
a = a.remove(word)
else:
pass
return a
But it returns back the string with the (Remove) word still in there. Any idea how I can achieve this?
A more terse way of doing this would be to form a regex alternation based on the list of words to remove, and then do a single regex substitution:
inp = "one two three four"
remove = ['two', 'four']
regex = r'\s*(?:' + r'|'.join(remove) + ')\s*'
out = re.sub(regex, ' ', inp).strip()
print(out) # prints 'one three'
You can try something more simple:
import re
remove_list = ['abc', 'cde', 'edf']
string = 'abc is walking with cde, wishing good luck to edf.'
''.join([x for x in re.split(r'(\W+)', string) if x not in remove_list])
And the result would be:
' is walking with , wishing good luck to .'
The important part is the last line:
''.join([x for x in re.split(r'(\W+)', string) if x not in remove_list])
What it does:
You are converthing the string to list of words with re.split(r'(\W+)', string), preserving all the whitespaces and punctuation as list items.
You are creating another list with list comprehension, filtering all the items, which are not in remove_list
You are converting the result list back to string with str.join()
The BNF notation for list comprehensions and a little bit more information on them may be found here
PS: Of course, you may make this a little bit more readable if you break the one-liner into peaces and assign the result of re.split(r'(\W+)', string) to a variable and decouple the join and the comprehension.
You can create a new list without the words you want to remove and then use join() function to concatenate all the words in that list. Try
def remove_words(string, rmlist):
final_list = []
word_list = string.split()
for word in word_list:
if word not in rmlist:
final_list.append(word)
return ' '.join(final_list)
list.remove(x) returns None and modifies the list in-place by removing x it exists inside the list. When you do
a = a.remove(word)
you will be effectively storing None in a and this would give an exception in the next iteration when you again do a.remove(word) (None.remove(word) is invalid), but you don’t get that either since you immediately return after the conditional (which is wrong, you need to return after the loop has finished, outside its scope). This is how your function should look like (without modifying a list while iterating over it):
remove_words = ["abc", ...] # your list of words to be removed
def remove_make(x):
a = x.split()
temp = a[:]
for word in temp:
if word in remove_words: # True
a.remove(word)
# no need of 'else' also, 'return' outside the loop's scope
return " ".join(a)

replace substrings in list

I am looking forward to get rid of a space that is after each element in my list:
list1 = ['Aena', 'Cellnex Telecom', 'Amadeus', 'Abertis']
in order to obtain the list like this:
list1 = ['Aena','Cellnex Telecom','Amadeus','Abertis']
I have tried the following loop but returns the same initial list:
new_list = [stocks.replace(" ","") for stocks in list1]
and
new_list = [stocks.replace(", '",",'") for stocks in list1]
print(new_list)
Could anyone help me to obtain the desired list without the spaces?
I think you have to understand, that print(..) prints the representation of a list (which is a comma separated list surrounded by square brackets).
With the list comprehension, you alter the elements themselves. As far as I know you can't do much about how print prints the list itself. But you can write your own print method.
We can do this by using a join on the repr(..) of the elements, and surround it by square brackets, like:
print('[{}]'.format(','.join(repr(x) for x in list1)))
This prints:
>>> print('[{}]'.format(','.join(repr(x) for x in list1)))
['Aena','Cellnex Telecom','Amadeus','Abertis']
>>> print('[{}]'.format(','.join(repr(x) for x in list1)))
['Aena','Cellnex Telecom','Amadeus','Abertis']

How to print items within lists in a list

Hear me out, I do not simply want someone to solve this problem for me. I know it is not 100% complete yet, but currently when I run the program I get an error about "Can't convert 'list' object to str implicitly" I'm looking for help on how to fix this and why it is does this.
Here is the problem
Write code to print out each thing in the list of lists, L, with a '*' after it like
1*2*3*4*...8*a*b*c*d*
This requires knowing the print statement and using the end or sep argument option
Here is my list, sorry for not putting it in earlier
L = [[1,2,3,4],[5,6,7,8],['a','b','c','d']]
Here is my code at the moment
def ball(x): #random function name with one parameter
q = '' #
i = 0
if type(x) != list: #verifies input is a list
return"Error"
for i in x: #Looks at each variable in list
for j in i: #Goes into second layer of lists
q = q + j + '*'
print(q)
The reason for your error
"Can't convert 'list' object to str implicitly"
is that you're using the wrong variable in your nested for loops. Where you're concatenating values to your q variable, you mistakenly put q = q + i when you wanted q = q + j. You also will want to cast the value of j as a string so it can be concatenated with q. In order to get your desired output, you can simply add an asterisk into that statement - something like the following: q = q + str(j) + '*'. On a completely unrelated note, your else statement that just has "Mistake" in it should be removed completely - it doesn't follow an if and it doesn't actually return or assign to a variable.
Note that this is not the most elegant way to go about solving this problem. I agree with ilent2 that you should take a look at both list comprehension and the str.join() method.
If you have a list of strings,
myList = ['a', '123', 'another', 'and another']
You can join them using the str.join function:
Help on method_descriptor:
join(...)
S.join(iterable) -> string
Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.
myString = '#'.join(myList)
If your list contains mixed types or non-strings you need to convert each item to a string first:
anotherList = [1, 2, 'asdf', 'bwsg']
anotherString = '*'.join([str(s) for s in anotherList])
You might want to read about list comprehension or more about the join function. Note, the above doesn't print the output (unless you are using the interactive console), if you want the output to be printed you will need call print too
print myString
print anotherString
And, if you are working with lists-of-lists you may need to change how you convert each sub-list into a string (depending on your desired output):
myListList = [[1, 2, 3, 4], [2, 3, 6, 5], [6, 4, 3, 1]]
myOtherString = '#'.join(['*'.join([str(s) for s in a]) for a in myListList])
The last line is a little complicated to read, you might want to rewrite it as a nested for loop instead.

generating a string representation of a list of tuples

I have a list of tuples of form
[("very", "ADJ"), ("slow", "ADJ"), ("programmer", "NOUN")]
My desired output is a single string of form:
"very/ADJ slow/ADJ programmer/NOUN"
This being python, I know I can do this in a one-liner using the format() and join() methods, but I can't get the syntax quite right. My most recent attempt was:
output_string = " ".join(["{0}/{1}".format(x) for x in list_of_tuples])
which threw an Index Error: tuple index out of range"
You want format(*x) so that the x tuple is expanded into arguments. Otherwise you are trying to call format with a single argument which is itself a tuple.
That said, if you know that these are all 2-tuples, I'd just go with the simpler:
output_string = " ".join(a + "/" + b for a, b in list_of_tuples)
Also note that there's no need to use a list comprehension to pass into join -- just use a generator comprehension instead.
words = [("very", "ADJ"), ("slow", "ADJ"), ("programmer", "NOUN")]
' '.join('/'.join((x,y)) for x,y in words)
You can use map too:
>>> ' '.join(map(lambda t: '{}/{}'.format(*t), li))
'very/ADJ slow/ADJ programmer/NOUN'
And, that same method without the lambda:
>>> ' '.join(map('/'.join, li))
'very/ADJ slow/ADJ programmer/NOUN'
Which works even if you have more than two elements in your tuples.

Converting lists of tuples to strings Python

I've written a function in python that returns a list, for example
[(1,1),(2,2),(3,3)]
But i want the output as a string so i can replace the comma with another char so the output would be
'1#1' '2#2' '3#3'
Any easy way around this?:)
Thanks for any tips in advance
This looks like a list of tuples, where each tuple has two elements.
' '.join(['%d#%d' % (t[0],t[1]) for t in l])
Which can of course be simplified to:
' '.join(['%d#%d' % t for t in l])
Or even:
' '.join(map(lambda t: '%d#%d' % t, l))
Where l is your original list. This generates 'number#number' pairs for each tuple in the list. These pairs are then joined with spaces (' ').
The join syntax looked a little weird to me when I first started woking with Python, but the documentation was a huge help.
You could convert the tuples to strings by using the % operator with a list comprehension or generator expression, e.g.
ll = [(1,1), (2,2), (3,3)]
['%d#%d' % aa for aa in ll]
This would return a list of strings like:
['1#1', '2#2', '3#3']
You can concatenate the resulting list of strings together for output. This article describes half a dozen different approaches with benchmarks and analysis of their relative merits.
' '.join([str(a)+"#"+str(b) for (a,b) in [(1,1),(2,2),(3,3)]])
or for arbitrary tuples in the list,
' '.join(['#'.join([str(v) for v in k]) for k in [(1,1),(2,2),(3,3)]])
In [1]: ' '.join('%d#%d' % (el[0], el[1]) for el in [(1,1),(2,2),(3,3)])
Out[1]: '1#1 2#2 3#3'
[ str(e[0]) + ',' + str(e[1]) for e in [(1,1), (2,2), (3,3)] ]
This is if you want them in a collection of string, I didn't understand it if you want a single output string or a collection.
[str(item).replace(',','#') for item in [(1,1),(2,2),(3,3)]]
You only need join and str in a generator comprehension.
>>> ['#'.join(str(i) for i in t) for t in l]
['1#1', '2#2', '3#3']
>>> ' '.join('#'.join(str(i) for i in t) for t in l)
'1#1 2#2 3#3'
you could use the repr function and then just replace bits of the string:
>>> original = [(1,1),(2,2),(3,3)]
>>> intermediate = repr(original)
>>> print intermediate
[(1, 1), (2, 2), (3, 3)]
>>> final = intermediate.replace('), (', ' ').replace('[(','').replace(')]','').replace(', ','#')
>>> print final
1#1 2#2 3#3
but this will only work if you know for certain that none of tuples have the following character sequences which need to be preserved in the final result: ), (, [(, )], ,

Categories