Remove words from list containing certain characters - python

I have a long list of words that I'm trying to go through and if the word contains a specific character remove it. However, the solution I thought would work doesn't and doesn't remove any words
l3 = ['b', 'd', 'e', 'f', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']
firstcheck = ['poach', 'omnificent', 'aminoxylol', 'teetotaller', 'kyathos', 'toxaemic', 'herohead', 'desole', 'nincompoophood', 'dinamode']
validwords = []
for i in l3:
for x in firstchect:
if i not in x:
validwords.append(x)
continue
else:
break
If a word from firstcheck has a character from l3 I want it removed or not added to this other list. I tried it both ways. Can anyone offer insight on what could be going wrong? I'm pretty sure I could use some list comprehension but I'm not very good at that.

The accepted answer makes use of np.sum which means importing a huge numerical library to perform a simple task that the Python kernel can easily do by itself:
validwords = [w for w in firstcheck if all(c not in w for c in l3)]

you can use a list comprehension:
import numpy as np
[w for w in firstcheck if np.sum([c in w for c in l3])==0]
It seems all the words contain at least 1 char from l3 and the output of above is an empty list.
If firstcheck is defined as below:
firstcheck = ['a', 'z', 'poach', 'omnificent']
The code should output:
['a', 'z']

If you want to avoid all loops etc, you can use re directly.
import re
l3 = ['b', 'd', 'e', 'f', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']
firstcheck = ['azz', 'poach', 'omnificent', 'aminoxylol', 'teetotaller', 'kyathos', 'toxaemic', 'herohead', 'desole', 'nincompoophood', 'dinamode']
# Create a regex string to remove.
strings_to_remove = "[{}]".format("".join(l3))
validwords = [x for x in firstcheck if re.sub(strings_to_remove, '', x) == x]
print(validwords)
Output:
['azz']

Ah, there was some mistake in code, rest was fine:
l3 = ['b', 'd', 'e', 'f', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y']
firstcheck = ['aza', 'ca', 'poach', 'omnificent', 'aminoxylol', 'teetotaller', 'kyathos', 'toxaemic', 'herohead', 'desole', 'nincompoophood', 'dinamode']
validwords = []
flag=1
for x in firstcheck:
for i in l3:
if i not in x:
flag=1
else:
flag=0
break
if(flag==1):
validwords.append(x)
print(validwords)
So, here the first mistake was, the for loops, we need to iterate through words first then, through l3, to avoid the readdition of elements.
Next, firstcheck spelling was wrong in 'for x in firstcheck` due to which error was there.
Also, I added a flag, such that if flag value is 1 it will add the element in validwords.
To, check I added new elements as 'aza' and 'ca', due to which, now it shows correct o/p as 'aza' and 'ca'.
Hope this helps you.

Related

How can I reference a string (e.g. 'A') to the index of a larger list (e.g. ['A', 'B', 'C', 'D', ...])?

I have been racking my brain and scouring the internet for some hours now, please help.
Effectively I am trying to create a self-contained function (in python) for producing a caesar cipher. I have a list - 'cache' - of all letters A-Z.
def caesarcipher(text, s):
global rawmessage #imports a string input - the 'raw message' which is to be encrypted.
result = ''
cache = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
Is it possible to analyze the string input (the 'rawmessage') and attribute each letter to its subsequent index position in the list 'cache'? e.g. if the input was 'AAA' then the console would recognise it as [0,0,0] in the list 'cache'. Or if the input was 'ABC' then the console would recognise it as [0,1,2] in the list 'cache'.
Thank you to anyone who makes the effort to help me out here.
Use a list comprehension:
positions = [cache.index(letter) for letter in rawmessage if letter in cache]
You can with a list comprehension. Also you can get the letter from string.
import string
print([string.ascii_uppercase.index(c) for c in "AAA"])
# [0, 0, 0]
print([string.ascii_uppercase.index(c) for c in "ABC"])
# [0, 1, 2]
result = []
for i in list(rawmessage):
result.append(cache.index(i))

Python: How to replace string elements using an array of tuples?

I'm trying to replace the characters of the reversed alphabet with those of the alphabet. This is what I've got:
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
rev_alphabet = alphabet[::-1]
sample = "wrw blf hvv ozhg mrtsg'h vkrhlwv?"
def f(alph, rev_alph):
return (alph, rev_alph)
char_list_of_tups = list(map(f, alphabet, rev_alphabet))
for alph, rev_alph in char_list_of_tups:
sample = sample.replace(rev_alph, alph)
print(sample)
expected output: did you see last night's episode?
actual output: wrw you svv ozst nrtst's vprsowv?
I understand that I'm printing the last "replacement" of the whole iteration. How can I avoid this without appending it to a list and then running into problems with the spacing of the words?
Your problem here is that you lose data as you perform each replacement; for a simple example, consider an input of "az". On the first replacement pass, you replace 'z' with 'a', and now have "aa". When you get to replacing 'a' with 'z', it becomes "zz", because you can't tell the difference between an already replaced character and one that's still unchanged.
For single character replacements, you want to use the str.translate method (and the not strictly required, but useful helper function, str.maketrans), to do character by character transliteration across the string in a single pass.
from string import ascii_lowercase # No need to define the alphabet; Python provides it
# You can use the original str form, no list needed
# Do this once up front, and reuse it for as many translate calls as you like
trans_map = str.maketrans(ascii_lowercase[::-1], ascii_lowercase)
sample = sample.translate(trans_map)
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
# or
alphabet = [chr(97 + i) for i in range(0,26)]
sample = "wrw blf hvv ozhg mrtsg'h vkrhlwv?"
res = []
for ch in sample:
if ch in alphabet:
res.append(alphabet[-1 - alphabet.index(ch)])
else:
res.append(ch)
print("".join(res))
Another Way if you are ok with creating a new string instead.
alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
dictRev = dict(zip(alphabet, alphabet[::-1]))
sample = "wrw blf hvv ozhg mrtsg'h vkrhlwv?"
s1="".join([dictRev.get(char, char) for char in sample])
print(s1)
"did you see last night's episode?"

Why doesn't my function remove all the things as programmed?

So I wrote a function that analyzes a text file and returns the text as a list excluding several characters like ('\n',' ','!','.','#','#')
I tried to program my code and used a sample text file filename which says I love Computer Science sooooooooooooooo much!!!!!
Now I expect my output to look like this...
['I', 'l', 'o', 'v', 'e', 'C', 'o', 'm', 'p', 'u', 't', 'e', 'r', 'S', 'c', 'i', 'e', 'n', 'c', 'e', 's', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'm', 'u', 'c', 'h']
but my output returns
['I', 'l', 'o', 'v', 'e', 'C', 'o', 'm', 'p', 'u', 't', 'e', 'r', 'S', 'c', 'i', 'e', 'n', 'c', 'e', 's', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'm', 'u', 'c', 'h', '!', '!']
but my code is programmed to remove the two '!' at the end....
What should I change in my code???
Here is my code btw...
def reverse(filename):
s = open(filename, 'r')
content = s.read()
g = list(content)
for x in g:
if x in ('\n',' ','!','.','#','#'):
g.remove(x)
return g
You can't modify a list while you are iterating through it. Well, you can, but it gets the iterator pointers screwed up. The right answer is to create a new list with the things you want to keep. And you don't have to convert the file to a list in order to iterate its contents. Strings are iterables, just like lists.
def reverse(filename):
s = open(filename, 'r')
g = []
for c in s.read():
if c not in '\n !.##':
g.append(c)
return g
Or:
def reverse(filename):
s = open(filename, 'r')
return [c for c in s.read() if c not in '\n !.##']
You can't iterate the list while removing the item from the same list because the index get changed so the best way is to iterate the list in reverse order
see the solution is :
def reverse(filename):
s = open(filename, 'r')
content = s.read()
g = list(content)
for x in reversed(g):
if x in ('\n',' ','!','.','#','#'):
g.remove(x)
return g
OUTPUT :
['I','l','o','v','e','C','o','m','p','u','t','e','r','S','c','i','e','n','c','e','s','o','o','o','o','o','o','o','o','o','o','o','o','o','o','o','m', 'u','c','h']
As Tim's answer says, the principled way to handle this is create a new list with the things you want to keep. That said, you might find it interesting that it is technically possible to remove items from the list without messing up the iterator pointer if you traverse the list backwards.
So with that said, here's a modification of your code that doesn't generate a separate list.
def reverse(filename):
s = open(filename, 'r')
content = s.read()
g = list(content)
for k in range(len(g))[::-1]:
if g[k] in ('\n',' ','!','.','#','#'):
g.pop(k)
return g
Note that unlike the "remove" function, the "pop" function does not require searching through the list when implemented.
Alternatively, as long as you're using the "remove" function, you can use the fact that the remove function searches through the list to avoid searching through the list "from scratch". Consider the following:
def reverse(filename):
s = open(filename, 'r')
content = s.read()
g = list(content)
for c in ('\n',' ','!','.','#','#'):
while c in g:
g.remove(c)
return g
Notably, the c in g check for the while condition consists of an extra search. We can avoid this by handling the exception of the remove function in the case that the character isn't found.
def reverse(filename):
s = open(filename, 'r')
content = s.read()
g = list(content)
for c in ('\n',' ','!','.','#','#'):
while True:
try:
g.remove(c)
except(ValueError):
break
return g
Might be more efficient to remove with str.replace:
def reverse(filename):
with open(filename) as f:
s = f.read()
for c in '\n !.##':
s = s.replace(c, '')
return list(s)
That goes over the string a few times, but such string methods are very fast.

Find all possible "real" word combinations from list in Python, up to x amount of words

I've been experimenting with itertools, combinations and enchant to find all possible (English) words from a list of characters, up to a set (x) amount of words, with no character limit for each word. Can't seem to find/create what I am looking for. Not looking for a handout or freebie, just genuinely stuck on a DnD cipher my friend passed along to me.
Basically, if I have:
char_list = ['i', 't', 'c', 'r', 'r', 's', 'f', 'o', 'k', 'p', 'a', 'e', 'u', 'a']
I'm trying to print:
possible_combos = [["xxx", "xxx", "xxx", "xxx"], ...]
Please don't laugh, but this is what I've been working with. I know it's not right, but I'm having a really hard time understanding exactly what I'm missing.
import itertools
lst = ['i', 't', 'c', 'r', 'r', 's', 'f', 'o', 'k', 'p', 'a', 'e', 'u', 'a']
combinatorics = itertools.product([True, False], repeat=len(lst) - 1)
solution = []
for combination in combinatorics:
i = 0
one_such_combination = [lst[i]]
for slab in combination:
i += 1
if not slab: # there is a join
one_such_combination[-1] += lst[i]
else:
one_such_combination += [lst[i]]
solution.append(one_such_combination)
print(solution)

How to make dictionary of alphabet and scrambled alphabet?

I need to create multiple dictionaries for another program using the alphabet as the key and a scrambled alphabet (the first one I have to do is BDFHJLCPRTXVZNYEIWGAKMUSQO) as the value. This is what I have so far but it says "unhashable type: 'list'"
_list = input("Enter list: ")
alpha = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
dict1 = {}
for i in range(0,len(_list)):
dict1[alpha][i] == _list[i]
print(dict1)
There are two errors in your code.
dict1[alpha][i] should be dict1[alpha[i]]
As pointed out by Paul Rooney, you cannot use a list as a dictionary key, but I don't think that is what you are trying to do. Instead, you just want the ith element of the list alpha.
the == should be =.
== is used to compare, = is used to assign a value.
Also, the pythonic way to do your iteration is as follows:
dict1 = {alpha[idx]: character for idx, character in enumerate(_list)}
which is the equivalent of
dict1 = {}
for idx, character in enumerate(_list):
dict1[alpha[idx]] = character

Categories