Python - check if letter is displayed in a row

I have a task when I need to read an input and check that this input is happening in some words. For example:

Who are your friends? Fred Bill Sue Simone
What is the message? Should you make tea?
Sue could have written this.

      

He types: "Sue could have written this because the letters" S "," U "and" E "appear in every consecutive word. Another example:

Who are your friends? James Nicky Jake
What is the message? join and make enough cash today!
James could have written this.
Jake could have written this.

      

Both titles are printed because both of their letters appear sequentially in each word. I have the following code:

friends = input("Who are your friends? ").split()
message = input("What is the message? ").split()

name = []
other = []

for friend in friends:
  for f in friend.lower():
    for word in message:
      print("checking if", f, "is in", word.lower())
      if f in word.lower():
        print("Adding", f, " to name list")
        name.append(f)
        break
      else:
        other.append(f)
        continue

joinedResult = ''.join(name)

for person in friends:
  if person.lower() in joinedResult:
    print(person, "could have written this.")

      

It works perfect for the first example, but for the second example it prints all three names:

James could have written this.
Nicky could have written this.
Jake could have written this.

      

I found out that the code does not check if the letters in the name will be sequential , but checks if the name is any word. How can I solve this?

+3


source to share


6 answers


def find_char(string, char):
    start_index = 0
    while True:
        yield string.lower().find(char, start_index)  # checks for the char in the string
        start_index += 1  # increments the index to find further in the word, 
        # eg: 
        # Bob constructed[index 0]
        # ob constructed[index 1]
        # b constructed[index 2]


def find_it(friends, message):
    friends = friends.split()
    for friend in friends:
        sequence_check = []
        for char in friend.lower():
            gen = find_char(message, char)  # creates the find_char generator
            for _ in message:  # limits the search to the length of the word
                char_index = next(gen) # try to find the index
                if char_index not in sequence_check: # if not in the sequence
                    sequence_check.append(char_index) # add it to it
                    break
        if -1 in sequence_check: # this check if every character of the name is in the word
            continue
        if sorted(sequence_check) == sequence_check: # this part check if it in a sequence.
            print (friend + ' could have written ' + message)


find_it('James Nicky Jake', "join and make enough cash today!")
find_it('Fred Bill Sue Simone', "Should you make tea?")
find_it("Bob", "Bob constructed Balloon Town")

      

Outputs:

James could have written join and make enough cash today!
Jake could have written join and make enough cash today!
Sue could have written Should you make tea?
Bob could have written Bob constructed Balloon Town

      



Rebuild it completely, now much cleaner.

Most of the work is done in the find_char function, which is a generator that has reduced the search space on each iteration, so it won't find Bob's place as [0,1,0], but [0,1, 2] in the sequence.

Any question feel free to ask.

+1


source


You can do this using zip

and all()

:

friends = input("Who are your friends? ").split()
message = input("What is the message? ").lower().split()

for friend in friends:
  if len(friend) <= len(message):
    if all(x in y for x, y in zip(friend.lower(), message)):
        print(friend, "could have written this.")

      



Demo:

>>> 
Who are your friends? Fred Bill Sue Simone
What is the message? Should you make tea?
Sue could have written this.
>>> 
Who are your friends? James Nicky Jake
What is the message? join and make enough cash today!
James could have written this.
Jake could have written this.

      

+3


source


Using a regex expression might be a little easier:

friends = raw_input("Who are your friends? ").split()
message = raw_input("What is the message? ").lower()

name = []
other = []

for friend in friends:
    regStr = '\w*\s?' + ''.join(['\w*' + f + '\w*\s' for f in friend.lower()])
    if re.match(regStr, message):
        name.append(friend)

for friend in name:
    print friend + " could have written this."

      

The regex style like: \w*\s?(s)\w*\s\w*(u)\w*\s\w*(e)\w*

for a friendSue

TestCase:

Shoulde i?

[no match] ( sue found but not sequentially => [S]ho[u]ld[e] i?

)

Should I make tea?

[no matches]

Should u make tea?

[sue]

+2


source


Note that you understand that the nth letter in their name must appear in the nth word in the message. Perhaps I am wrong on this and you can clarify.

You need to combine each letter in your name with a word from the message and then check for inclusion. You can do this usingzip

friends = 'James Nicky Jake'.split()
message = 'join and make enough cash today!'.split()

names = []
others = []

for friend in friends:
    match = True
    length = len(friend)

    for letter, word in zip(friend.lower(), message):
        if not letter in word.lower():
            match = False
            break

    if match:
        names.append(friend)
    else:
        others.append(friend)

for person in names:
        print(person, "could have written this.")

      

+1


source


friends=["James","Nicky","Jake"]
words=["James could have written this","Jake could have written this"]
for friend in friends:
    for word in words:
        for name in word.split():
            if friend.lower()==name.lower():
                print friend,"yes"
            else:
                print friend,"no"

      

You can use this simple code rather than comparing letter

with letter

, which is also error prone, since letters can be anywhere in a string, not necessarily contiguous.

0


source


Code

def whosdoneit(names,message):
    good_names = []
    l_m = len(message)
    for name in names:
        if len(name) > l_m: continue
        if all(c.lower() in word.lower() for c, word in zip(name, message)):
            good_names.append(name)
    return good_names

print whosdoneit('Fred Bill Sue Simone'.split(),
                 'Should you make tea?'.split())

print whosdoneit('James Nicky Jake'.split(),
                 'join and make enough cash today!'.split())

      

Output

['Sue']
['James', 'Jake']

      

A comment

The function returns a list of good names, people who could write a para-acrostic containing their name, so

  • we start to initialize the list with a null list

Next, we will note that the name cannot be more than the number of words in the message, it can meet the requirements, so to use it later,

  • we calculate and store the length, in words of the message

Now

  • we iterate over the list names

    to check if it matches the name

    rules

    • if the name is too long, further processing

    • using zip

      , we build a list of pairs, character c

      in name

      , word

      in message

      , and we build a list of gates using a list comprehension

    • if all

      booleans are true ( all

      and any

      are useful builtins!) then add name

      to the listgood_names

  • returns a list of good names to the caller.

I've also included a few function calls that mimic the OP's examples.

Possibly the highly anticipated one-liner

s

for suspects ...

def s(n,m):return [g for l in [len(m)] for g in n if len(g)<=l and all([c.lower() in w.lower() for c,w in zip(g,m)])]

      

0


source







All Articles