3

I need to know how to identify prefixes in strings in a list. For example,

list = ['nomad', 'normal', 'nonstop', 'noob']

Its answer should be 'no' since every string in the list starts with 'no'

I was wondering if there is a method that iterates each letter in strings in the list at the same time and checks each letter is the same with each other.

Georgy
  • 12,464
  • 7
  • 65
  • 73
Nicholas An
  • 156
  • 1
  • 9

4 Answers4

16

Use os.path.commonprefix it will do exactly what you want.

In [1]: list = ['nomad', 'normal', 'nonstop', 'noob']

In [2]: import os.path as p

In [3]: p.commonprefix(list)
Out[3]: 'no'

As an aside, naming a list "list" will make it impossible to access the list class, so I would recommend using a different variable name.

RedKnite
  • 1,525
  • 13
  • 26
7

Here is a code without libraries:

for i in range(len(l[0])):
    if False in [l[0][:i] == j[:i] for j in l]:
        print(l[0][:i-1])
        break

gives output:

no
Joshua Varghese
  • 5,082
  • 1
  • 13
  • 34
2

There is no built-in function to do this. If you are looking for short python code that can do this for you, here's my attempt:

def longest_common_prefix(words):
    i = 0
    while len(set([word[:i] for word in words])) <= 1:
        i += 1
    return words[0][:i-1]

Explanation: words is an iterable of strings. The list comprehension

[word[:i] for word in words]

uses string slices to take the first i letters of each string. At the beginning, these would all be empty strings. Then, it would consist of the first letter of each word. Then the first two letters, and so on.

Casting to a set removes duplicates. For example, set([1, 2, 2, 3]) = {1, 2, 3}. By casting our list of prefixes to a set, we remove duplicates. If the length of the set is less than or equal to one, then they are all identical.

The counter i just keeps track of how many letters are identical so far.

We return words[0][i-1]. We arbitrarily choose the first word and take the first i-1 letters (which would be the same for any word in the list). The reason that it's i-1 and not i is that i gets incremented before we check if all of the words still share the same prefix.

2

Here's a fun one:

l = ['nomad', 'normal', 'nonstop', 'noob']

def common_prefix(lst):
    for s in zip(*lst):
        if len(set(s)) == 1:
            yield s[0]
        else:
            return

result = ''.join(common_prefix(l))

Result:

'no'

To answer the spirit of your question - zip(*lst) is what allows you to "iterate letters in every string in the list at the same time". For example, list(zip(*lst)) would look like this:

[('n', 'n', 'n', 'n'), ('o', 'o', 'o', 'o'), ('m', 'r', 'n', 'o'), ('a', 'm', 's', 'b')]

Now all you need to do is find out the common elements, i.e. the len of set for each group, and if they're common (len(set(s)) == 1) then join it back.


As an aside, you probably don't want to call your list by the name list. Any time you call list() afterwards is gonna be a headache. It's bad practice to shadow built-in keywords.

r.ook
  • 13,466
  • 2
  • 22
  • 39