FAQ: Introduction to Strings - Strings and Conditionals (Part Two)

This community-built FAQ covers the “Strings and Conditionals (Part Two)” exercise from the lesson “Introduction to Strings”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Computer Science

FAQs on the exercise Strings and Conditionals (Part Two)

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

3 posts were split to a new topic: I can just use return?

19 posts were split to a new topic: How to not get duplicate letters?

2 posts were split to a new topic: Used a brute force method; is it a bit messy?

hello,
need to know the mistake in this code
def contains(big_string, little_string):
for character in big_string:
if character == little_string:
return True
and when i look at the solution i don’t understand the answer of the first Q

This will return on the first True, meaning iteration will not be complete. Be sure to completely compare little_string.

Think in terms of slices. We can measure the length of little_string and then iterate over big_string and compare equal length slices when the first letter of little_string is encountered.

What’s more, the above is comparing a character to a string, not a character.

While this is not the recommended solution, since it is not an algorithm (the preferred solution at this level)…

 return little_string in big_string

The above uses membership testing with the in operator. Our algorithm will want to emulate this, but in a loop construct.

def contains(haystack, needle):
    n = len(needle)
    f = needle[0]
    for i, x in enumerate(haystack):
        if x == f:
            if haystack[i:n + i] == needle:
                return True
    return False

print (contains('superimposed', 'impose'))    # True

Now if we assume that the enumerate function is as yet unknown to you, then we can revert to range to obtain the index, and the current character.

for i in range(len(big_string)):
    if big_string[i] == f:
        if big_string[i:n + i] == little_string:

Of course, the above solutions both assume that you are familiar with slicing. If not, then we need to get more creative using only the concepts currently in your tool belt.


We’re now eight hours later, and have this to consider that uses none of the above, only the range, as suggested.

# without slicing or enumerate
def has_in(haystack, needle):
  k = range(len(needle))
  h = range(len(haystack))
  f = needle[0]
  r = False
  for i in h:
    if haystack[i] == f:
      for j in k:
        if haystack[i + j] == needle[j]:
          r = True
          continue
        else:
          r = False
          break
      if r: return r
  return r

print (has_in('superimposed self-imposed', 'impose'))      # True
print (has_in('superimposed self-imposed', 'imposter'))    # False

https://repl.it/@mtf/needle-haystack-found-string-in-string

Above we could technically return the index, as well, but it would be to the first match, not subsequent matches. That will take more logic.

Such as,

def has_at(haystack, needle):
  k = range(len(needle))
  h = range(len(haystack) - k[-1])
  f = needle[0]
  r = False
  s = []
  for i in h:
    if haystack[i] == f:
      for j in k:
        if haystack[i + j] == needle[j]:
          r = True
          continue
        else:
          r = False
          break
      if r: s.append(i)
  return s or r

print (has_at('superimposed self-imposed impose', 'impose'))      # [5, 18, 26]
print (has_at('superimposed self-imposed impose', 'imposter'))    # False

Why in my code i get {“a”, “n”} instead of [“a”, “n”]

def common_letters(string_one, string_two):
letters =
for L in string_one:
if L in string_two:
letters += L
letters.sort()
return set(letters)

The return value is a set; ergo, the delimiters, { and }.

Hello!

I know that I’ve tried to solve it differently by going at it differently and not using “in” for both parameters and I’ve understood how to answer the question.

However, I’m having trouble understanding why the code I’ve written always seems to be returning an empty list.

def common_letters(string_one, string_two):
  common_lst = []
  for char1 in string_one:
    for char2 in string_two:
      if char1 == char2 and char1 not in common_lst == True:
        common_lst.append(char1)
  return common_lst

**Edit:

I’ve also tried changing the indentation of the return common_lst with no avail. So far I understand the concepts taught in this course pretty well, but for some reason I always struggle with indentation!

Unnecessary to write == True.

Is it really necessary to iterate both strings? Consider that in is a sort of iterator as it seeks membership. Iterating over one string (either one) and searching in the other will certainly detect any matches.

Hi mtf,

Could you please clarify what you mean regarding in?

in returns True or False all by itself. You don’t need to add == True.

my_str = 'abcde'
print('abc' in my_str)
print('xyz' in my_str)

Output:

True
False

Incidentally, due to operator precedence, and the way chaining works, your expression won’t work as you expect:

print('xyz' not in my_str ==  True)

Output:

False

The chained expression is evaluated as follows:

('xyz' not in my_str) and (my_str ==  True)

… which returns False, since the second term returns False.

2 Likes

Woah. Took me a good minute to see that there was comparison chaining there even after you said it. That’s pretty surprising. I’d never write that, but I’d also never spot it by only reading it.

1 Like

Owing that in (membership) and == (identity) have equal precedence, operations occur from left to right

'xyz' not in my_str  => True
True == True         => True

…no
but that’s how I would first read it, too.

1 Like
>>> my_str = 'abcdef'
>>> 'xyz' not in my_str
True
>>> 'xyz' not in my_str == True
False
>>> 

I stand corrected, thank you.

1 Like

This time explicitly made sure I used loops :stuck_out_tongue: haha

def contains(big_string, little_string):
  maybe = False
  if big_string.count(little_string):
    maybe = True
  return maybe

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

Silliness

>>> def common_letters(a, b):
	r = {}
	c, d = (a, b) if len(a) < b else (b, a)
	for x in c:
		if x in d:
			r[x] = 1
	return list(r.keys())

>>> common_letters('impossible', 'impasse')
['i', 'p', 's', 'm', 'e']
>>> 

Even sillier…

>>> def common_letters(a, b):
	if len(a) > b: a, b = b, a
	return list({x: 1 for x in a if x in b}.keys())

>>> common_letters('impossible', 'impasse')
['i', 'p', 's', 'm', 'e']
>>> 

The latter comes up in advanced topics later in the course (if they haven’t been covered yet)… dictionary comprehensions.

1 Like

Couple of observations.

  • In a previous exercise you returned a bool with a single line. Why not here in contains()?

  • In common_letters what difference does it make which list is longer?

We really only need to iterate the shorter list and check for membership in the longer one.

1 Like