How to not get duplicate letters?

Several people in this post have mentioned not knowing about the “not” operator. I’m curious about this. I’m not taking this course so I don’t know what the order of topics being covered is but certainly “if” statements must have been. Generally when learning about “if” statements the comparison operators ie. (>, <, >=, etc ) as well as the logical operators (“and”, “or”, and “not”) are also introduced. Is this not the case?

1 Like

Just to emphasize, the parentheses around “letter in common” are VERY important. If it isn’t written as
such but rather “not letter in common” the expression will evaluate to “not letter (in common)”. These two expressions are completely different and won’t give the same result.

That is how I also solved it, but compressed it a little bit more with “and not”:

def common_letters(string_one, string_two):
  output = []
  for i in range(len(string_one)):
    if string_one[i] in string_two and not string_one[i] in output:
      output.append(string_one[i])
  return output

I the letter in position string_one[i] returns TRUE as per first condition AND is not already present in output, then it appends said letter to the list output :slight_smile:

Should that be,

output.append(...)
^^^^^^

apologies, I edited the code I pasted but forgot that bit…

1 Like

Same happened to me, with this line I fixed it:

if letters in common_letters:
        continue

whole code is below:

def common_letters(string_one, string_two):
  common_letters = []
  for letters in string_one:
    if letters in string_two:
      if letters in common_letters:
        continue
      common_letters.append(letters)
  return common_letters

You can combine conditions with and/or

1 Like

Yes, I saw it minutes after I posted :slight_smile: thank you.

Is there is a better answer or this one is good enough?

def common_letters(string_one, string_two):
  new_lst = []
  for char in string_one:
    if char in string_two:
      if char not in new_lst:
          new_lst.append(char)

  return new_lst

The proper way to do this is to use sets to do membership testing without searching.

If you’re going to only use list and string operations then that’s fair. An argument could be made about not using in and instead implement it yourself to make it obvious to you that membership testing for list/string involves searching through the whole thing (or at least up until a match)

1 Like

I did not think of the “and not” keywords, so I used the XOR operator that is common in Java and Python. The ^ operator, also known as XOR or exclusive or operator, only returns true if the 2 input values are different.

In binary terms, or True/False logic:
0 / False ^ 0 / False --> 0 / False
0 / False ^ 1 / True --> 1 / True
1 / True ^ 0 / False --> 1 / True
1 / True ^ 1 / True --> 0 / False

In the case of my code, or this exercise, I know that I do not want to add the letter into the new list if:

  1. The letter in string_1 is not even found in string_2. (thus the letter would definitely not be in the new list)
  2. The letter is common in both strings, but has already been added to the new list.

In case 1, the input will be False and False, hence the boolean output is still False and the letter will not be added into the list.
In case 2, the input will be True and True, hence the boolean output is still False and the letter will not be added into the list.

The only possible way to add the letter to the list is if it appears in both strings and has not been added into the list, thus giving a True and False input. Since the inputs differ, the boolean output is true, and the code is run.

For the input to be False and True, the letter must not be common in both strings, yet is already in the list. This very scenario is a paradox and will never happen.

My code is attached below, you may refer for a better understanding of the XOR ^ operator.

My minimalist solution creates an empty list first, which will be returned with the unique characters in common to the two strings.

It then loops through the first string, effectively one element (or character) as we are told, at a time. The first line inside the loop checks using the “in” operator/operation to see if this character c exists in the second string. But, since I used a compound if condition, meaning the “AND” conditional operator, both the first expression and the second expression MUST be true in order for the whole if statement to be true. If the whole thing is true, then append the letter stored in c to the list.

I guess I got lucky that the “not in” expression worked, because until I tried it, I wasn’t sure it would work, but it seems to work well.

def common_letters(string_one, string_two):

  lst = []

  for c in string_one:

    if c in string_two and c not in lst:

      lst.append(c)

  return lst

print(common_letters("banana", "cream"))
for c in shortest_string:

Hint, hint.

This was very helpful. Thank you!

1 Like

I’m glad I wasn’t the only one who didn’t realize I could use “not if” as well as combine it in one conditional statement with “and.” I found a solution with the following code. Is this an acceptable answer, or is there a reason I should not do it this way? Thanks in advance!

def common_letters(string_one, string_two):
common_list =
for char in string_one:
if char in common_list:
continue
if char in string_two:
common_list += char
return common_list

Not a definitive one, no. It makes sense. However, since we are working with strings why not just use a common_str then cast it to a list on the return?

    common_str += char

return list(common_str)

This assumes the return value is supposed to be a list.


Recall that += (augmented assignment) when used with mutable sequences requires that both sides of the assignment are iterable.

>>> s = []
>>> s += 'a'
>>> s
['a']
>>> s += 1
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    s += 1
TypeError: 'int' object is not iterable
>>> s += 1, 2
>>> s
['a', 1, 2]
>>> 

Sometimes it is better to be explicit.

s.append(value)

applies explicitly to list objects. We know that s is a list because only list has an append attribute.

1 Like

This explaination of .append() vs += makes a lot of sense, thank you!

1 Like

Thank you. It’s frustrating when the solution contains stuff they haven’t taught yet. Most of the exercises are great, but in my couple weeks here I’ve found multiple instances of them expecting something that hasn’t been introduced yet. Since we’re not psychic, I don’t know why they expect us to magically know things before they’ve taught them.

1 Like

This is so cool and simple! solution

I had this solution below which is straight forward. It first checks if an element in string_one is in string_two, then checks whether that element is already in the common_letters list… if the ele is not in the common_letters list, its appended, else, the loop continues!

def common_letters(string_one, string_two):
  common_letters = []
  for ele in string_one:
    if ele in string_two:
      if ele not in common_letters:
        common_letters.append(ele)
  return common_letters
2 Likes